Explorar o código

display: Support extracting only subset of SSBO

rdb hai 1 mes
pai
achega
86b1304588

+ 4 - 3
panda/src/display/graphicsEngine.cxx

@@ -1145,15 +1145,16 @@ extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg) {
  *
  * This is mainly useful for debugging.  It is a very slow call because it
  * introduces a pipeline stall both of Panda's pipeline and the graphics
- * pipeline.
+ * pipeline.  This is even when only a small amount of data is downloaded.
  *
  * The return value is empty if some kind of error occurred.
  */
 vector_uchar GraphicsEngine::
-extract_shader_buffer_data(ShaderBuffer *buffer, GraphicsStateGuardian *gsg) {
+extract_shader_buffer_data(ShaderBuffer *buffer, GraphicsStateGuardian *gsg,
+                           size_t start, size_t size) {
   return run_on_draw_thread([=] () {
     vector_uchar data;
-    if (!gsg->extract_shader_buffer_data(buffer, data)) {
+    if (!gsg->extract_shader_buffer_data(buffer, data, start, size)) {
       data.clear();
     }
     return data;

+ 2 - 1
panda/src/display/graphicsEngine.h

@@ -115,7 +115,8 @@ PUBLISHED:
   BLOCKING void flip_frame();
 
   bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg);
-  vector_uchar extract_shader_buffer_data(ShaderBuffer *buffer, GraphicsStateGuardian *gsg);
+  vector_uchar extract_shader_buffer_data(ShaderBuffer *buffer, GraphicsStateGuardian *gsg,
+                                          size_t start = 0, size_t size = (size_t)-1);
   void dispatch_compute(const LVecBase3i &work_groups,
                         const RenderState *state,
                         GraphicsStateGuardian *gsg);

+ 2 - 1
panda/src/display/graphicsStateGuardian.cxx

@@ -774,7 +774,8 @@ release_shader_buffers(const pvector<BufferContext *> &contexts) {
  * current contents synchronously.
  */
 bool GraphicsStateGuardian::
-extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data) {
+extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
+                           size_t start, size_t size) {
   return false;
 }
 

+ 2 - 1
panda/src/display/graphicsStateGuardian.h

@@ -326,7 +326,8 @@ public:
   virtual BufferContext *prepare_shader_buffer(ShaderBuffer *data);
   virtual void release_shader_buffer(BufferContext *ibc);
   virtual void release_shader_buffers(const pvector<BufferContext *> &contexts);
-  virtual bool extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data);
+  virtual bool extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
+                                          size_t start = 0, size_t size = (size_t)-1);
 
   virtual void begin_occlusion_query();
   virtual PT(OcclusionQueryContext) end_occlusion_query();

+ 10 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -7766,14 +7766,21 @@ release_shader_buffers(const pvector<BufferContext *> &contexts) {
  * current contents synchronously.
  */
 bool CLP(GraphicsStateGuardian)::
-extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data) {
+extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
+                           size_t start, size_t size) {
   BufferContext *bc = buffer->prepare_now(get_prepared_objects(), this);
   if (bc == nullptr || !bc->is_of_type(CLP(BufferContext)::get_class_type())) {
     return false;
   }
   CLP(BufferContext) *gbc = DCAST(CLP(BufferContext), bc);
 
-  data.resize(buffer->get_data_size_bytes());
+  size_t total_size = buffer->get_data_size_bytes();
+  if (start >= total_size) {
+    data.clear();
+    return true;
+  }
+
+  data.resize(std::min(total_size - start, size));
 
   if (_glMemoryBarrier != nullptr) {
     _glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
@@ -7781,7 +7788,7 @@ extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data) {
 
   _glBindBuffer(GL_SHADER_STORAGE_BUFFER, gbc->_index);
 
-  _glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, data.size(), &data[0]);
+  _glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, start, data.size(), &data[0]);
 
   _glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
   _current_sbuffer_index = 0;

+ 2 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -399,7 +399,8 @@ public:
   CLP(BufferContext) *apply_shader_buffer(GLuint base, ShaderBuffer *buffer);
   virtual void release_shader_buffer(BufferContext *bc);
   virtual void release_shader_buffers(const pvector<BufferContext *> &contexts);
-  virtual bool extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data);
+  virtual bool extract_shader_buffer_data(ShaderBuffer *buffer, vector_uchar &data,
+                                          size_t start, size_t size);
 #endif
 
 #ifndef OPENGLES

+ 7 - 2
tests/display/test_glsl_shader.py

@@ -301,7 +301,7 @@ def test_glsl_uimage(gsg):
 def test_glsl_ssbo(gsg):
     from struct import pack, unpack
     num1 = pack('<i', 1234567)
-    num2 = pack('<i', -1234567)
+    num2 = pack('<ii', -1234567, 867451)
     buffer1 = core.ShaderBuffer("buffer1", num1, core.GeomEnums.UH_static)
     buffer2 = core.ShaderBuffer("buffer2", num2, core.GeomEnums.UH_static)
 
@@ -311,11 +311,13 @@ def test_glsl_ssbo(gsg):
     };
     layout(std430, binding=1) buffer buffer2 {
         int value2;
+        int value3;
     };
     """
     code = """
     assert(value1 == 1234567);
     assert(value2 == -1234567);
+    assert(value3 == 867451);
     value1 = 98765;
     value2 = 5343525;
     """
@@ -328,7 +330,10 @@ def test_glsl_ssbo(gsg):
     assert unpack('<i', data1[:4]) == (98765, )
 
     data2 = gsg.get_engine().extract_shader_buffer_data(buffer2, gsg)
-    assert unpack('<i', data2[:4]) == (5343525, )
+    assert unpack('<ii', data2[:8]) == (5343525, 867451)
+
+    data3 = gsg.get_engine().extract_shader_buffer_data(buffer2, gsg, 4, 8)
+    assert unpack('<i', data3[:4]) == (867451, )
 
 
 def test_glsl_int(gsg):