parent
cb03554da5
commit
136e1279ea
|
|
@ -792,6 +792,16 @@ extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous version of extract_shader_buffer_data. It is the caller's
|
||||
* responsibility that the data argument outlasts the token.
|
||||
*/
|
||||
void GraphicsStateGuardian::
|
||||
async_extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
|
||||
size_t start, size_t size, CompletionToken token) {
|
||||
token.complete(extract_shader_buffer_data(buffer, data, start, size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins a new occlusion query. After this call, you may call
|
||||
* begin_draw_primitives() and draw_triangles()/draw_whatever() repeatedly.
|
||||
|
|
|
|||
|
|
@ -330,6 +330,9 @@ public:
|
|||
size_t size, const unsigned char *data);
|
||||
virtual bool extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
|
||||
size_t start = 0, size_t size = (size_t)-1);
|
||||
virtual void async_extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
|
||||
size_t start = 0, size_t size = (size_t)-1,
|
||||
CompletionToken token = CompletionToken());
|
||||
|
||||
virtual void begin_occlusion_query();
|
||||
virtual PT(OcclusionQueryContext) end_occlusion_query();
|
||||
|
|
|
|||
|
|
@ -7843,6 +7843,60 @@ extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENGLES
|
||||
/**
|
||||
* Asynchronous version of extract_shader_buffer_data. It is the caller's
|
||||
* responsibility that the data argument outlasts the token.
|
||||
*/
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
async_extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
|
||||
size_t start, size_t size, CompletionToken token) {
|
||||
BufferContext *bc = buffer->prepare_now(get_prepared_objects(), this);
|
||||
if (bc == nullptr || !bc->is_of_type(CLP(BufferContext)::get_class_type())) {
|
||||
token.complete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
CLP(BufferContext) *gbc = DCAST(CLP(BufferContext), bc);
|
||||
|
||||
size_t total_size = buffer->get_data_size_bytes();
|
||||
if (start >= total_size) {
|
||||
data.clear();
|
||||
token.complete(true);
|
||||
return;
|
||||
}
|
||||
|
||||
size = std::min(total_size - start, size);
|
||||
|
||||
GLuint staging_buffer = 0;
|
||||
void *mapped_ptr = nullptr;
|
||||
|
||||
bind_new_client_buffer(staging_buffer, mapped_ptr, GL_COPY_WRITE_BUFFER, size);
|
||||
if (_glMemoryBarrier != nullptr) {
|
||||
_glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
|
||||
}
|
||||
|
||||
_glBindBuffer(GL_SHADER_STORAGE_BUFFER, gbc->_index);
|
||||
_glCopyBufferSubData(GL_SHADER_STORAGE_BUFFER, GL_COPY_WRITE_BUFFER, start, 0, size);
|
||||
_glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||
_glBindBuffer(GL_COPY_READ_BUFFER, 0);
|
||||
_current_sbuffer_index = 0;
|
||||
|
||||
if (_supports_buffer_storage && _glMemoryBarrier != nullptr) {
|
||||
_glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
|
||||
}
|
||||
|
||||
insert_fence([=, &data, token = std::move(token)] (bool success) mutable {
|
||||
if (success) {
|
||||
data = vector_uchar((const unsigned char *)mapped_ptr, (const unsigned char *)mapped_ptr + size);
|
||||
token.complete(true);
|
||||
} else {
|
||||
token.complete(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENGLES
|
||||
/**
|
||||
* Begins a new occlusion query. After this call, you may call
|
||||
|
|
|
|||
|
|
@ -403,6 +403,9 @@ public:
|
|||
size_t size, const unsigned char *data);
|
||||
virtual bool extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
|
||||
size_t start, size_t size);
|
||||
virtual void async_extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
|
||||
size_t start = 0, size_t size = (size_t)-1,
|
||||
CompletionToken token = CompletionToken());
|
||||
#endif
|
||||
|
||||
#ifndef OPENGLES
|
||||
|
|
|
|||
|
|
@ -1380,6 +1380,15 @@ prepare_shader_buffer_now(ShaderBuffer *data, GraphicsStateGuardianBase *gsg) {
|
|||
return bc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the given function to be called during the next begin_frame().
|
||||
*/
|
||||
void PreparedGraphicsObjects::
|
||||
enqueue_call(EnqueuedCall &&call) {
|
||||
ReMutexHolder holder(_lock);
|
||||
_enqueued_calls.push_back(std::move(call));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new future for the given object.
|
||||
*/
|
||||
|
|
@ -1601,6 +1610,12 @@ begin_frame(GraphicsStateGuardianBase *gsg, Thread *current_thread) {
|
|||
}
|
||||
|
||||
_enqueued_shader_buffers.clear();
|
||||
|
||||
for (EnqueuedCall &call : _enqueued_calls) {
|
||||
std::move(call)(gsg);
|
||||
}
|
||||
|
||||
_enqueued_calls.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@
|
|||
#include "adaptiveLru.h"
|
||||
#include "asyncFuture.h"
|
||||
|
||||
#ifndef CPPPARSER
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
class TextureContext;
|
||||
class SamplerContext;
|
||||
class GeomContext;
|
||||
|
|
@ -160,6 +164,12 @@ PUBLISHED:
|
|||
GraphicsStateGuardianBase *gsg);
|
||||
|
||||
public:
|
||||
#ifndef CPPPARSER
|
||||
typedef std::function<void (GraphicsStateGuardianBase *gsg)> EnqueuedCall;
|
||||
|
||||
void enqueue_call(EnqueuedCall &&call);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This is a handle to an enqueued object, from which the result can be
|
||||
* obtained upon completion.
|
||||
|
|
@ -281,6 +291,7 @@ private:
|
|||
Buffers _prepared_shader_buffers;
|
||||
pvector<BufferContext *> _released_shader_buffers;
|
||||
EnqueuedShaderBuffers _enqueued_shader_buffers;
|
||||
pvector<EnqueuedCall> _enqueued_calls;
|
||||
|
||||
BufferCache _vertex_buffer_cache;
|
||||
BufferCacheLRU _vertex_buffer_cache_lru;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,26 @@ output(std::ostream &out) const {
|
|||
out << "buffer " << get_name() << ", " << _data_size_bytes << "B, " << _usage_hint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously requests to read the given subset of the data on the CPU.
|
||||
*/
|
||||
PT(AsyncFuture) ShaderBuffer::
|
||||
extract_data(PreparedGraphicsObjects *prepared_objects, size_t start, size_t size) {
|
||||
PT(AsyncFuture) future = new AsyncFuture;
|
||||
PT(ParamBytes) bytes = new ParamBytes(vector_uchar());
|
||||
|
||||
prepared_objects->enqueue_call([=, bytes = std::move(bytes)] (GraphicsStateGuardianBase *gsg) {
|
||||
gsg->async_extract_shader_buffer_data(this, (vector_uchar &)bytes->get_value(), start, size, [future = std::move(future), bytes = std::move(bytes)] (bool success) {
|
||||
if (success) {
|
||||
future->set_result(bytes);
|
||||
} else {
|
||||
future->set_result(nullptr);
|
||||
}
|
||||
});
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the data should be enqueued to be prepared in the indicated
|
||||
* prepared_objects at the beginning of the next frame. This will ensure the
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "graphicsStateGuardianBase.h"
|
||||
#include "factoryParams.h"
|
||||
#include "vector_uchar.h"
|
||||
#include "asyncFuture.h"
|
||||
|
||||
class BufferContext;
|
||||
class PreparedGraphicsObjects;
|
||||
|
|
@ -51,6 +52,9 @@ PUBLISHED:
|
|||
MAKE_PROPERTY(data_size_bytes, get_data_size_bytes);
|
||||
MAKE_PROPERTY(usage_hint, get_usage_hint);
|
||||
|
||||
PT(AsyncFuture) extract_data(PreparedGraphicsObjects *prepared_objects,
|
||||
size_t start = 0, size_t size = (size_t)-1);
|
||||
|
||||
void prepare(PreparedGraphicsObjects *prepared_objects);
|
||||
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "patomic.h"
|
||||
#include "small_vector.h"
|
||||
#include "completionToken.h"
|
||||
#include "vector_uchar.h"
|
||||
|
||||
// A handful of forward references.
|
||||
|
||||
|
|
@ -32,6 +33,7 @@ class GraphicsWindow;
|
|||
class NodePath;
|
||||
class GraphicsOutputBase;
|
||||
class ScreenshotRequest;
|
||||
class AsyncFuture;
|
||||
|
||||
class VertexBufferContext;
|
||||
class IndexBufferContext;
|
||||
|
|
@ -175,6 +177,9 @@ public:
|
|||
virtual BufferContext *prepare_shader_buffer(ShaderBuffer *data)=0;
|
||||
virtual void release_shader_buffer(BufferContext *ibc)=0;
|
||||
virtual void release_shader_buffers(const pvector<BufferContext *> &contexts)=0;
|
||||
virtual void async_extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
|
||||
size_t start = 0, size_t size = (size_t)-1,
|
||||
CompletionToken token = CompletionToken())=0;
|
||||
|
||||
virtual void dispatch_compute(int size_x, int size_y, int size_z)=0;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue