From 6dfe4ab030a2281f52610bf888d03c11a34029d2 Mon Sep 17 00:00:00 2001 From: aignacio_sf <> Date: Wed, 13 Feb 2008 01:08:36 +0000 Subject: [PATCH] Add depth buffer sharing. --- panda/src/display/graphicsOutput.cxx | 21 +++ panda/src/display/graphicsOutput.h | 3 + panda/src/dxgsg9/wdxGraphicsBuffer9.cxx | 197 ++++++++++++++++++--- panda/src/dxgsg9/wdxGraphicsBuffer9.h | 10 ++ panda/src/glstuff/glGraphicsBuffer_src.cxx | 134 +++++++++++++- panda/src/glstuff/glGraphicsBuffer_src.h | 9 + 6 files changed, 349 insertions(+), 25 deletions(-) diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index 7d3f7036b8..fcd5a86eca 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -1218,3 +1218,24 @@ operator << (ostream &out, GraphicsOutput::FrameMode fm) { return out << "(**invalid GraphicsOutput::FrameMode(" << (int)fm << ")**)"; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::share_depth_buffer +// Access: Published, Virtual +// Description: Will attempt to use the depth buffer of the input +// graphics_output. The buffer sizes must be exactly +// the same. +//////////////////////////////////////////////////////////////////// +bool GraphicsOutput:: +share_depth_buffer(GraphicsOutput *graphics_output) { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::unshare_depth_buffer +// Access: Published, Virtual +// Description: Discontinue sharing the depth buffer. +//////////////////////////////////////////////////////////////////// +void GraphicsOutput:: +unshare_depth_buffer() { + +} diff --git a/panda/src/display/graphicsOutput.h b/panda/src/display/graphicsOutput.h index 5f9fdb7194..3094ba8201 100644 --- a/panda/src/display/graphicsOutput.h +++ b/panda/src/display/graphicsOutput.h @@ -194,6 +194,9 @@ PUBLISHED: NodePath get_texture_card(); + virtual bool share_depth_buffer(GraphicsOutput *graphics_output); + virtual void unshare_depth_buffer(); + public: // These are not intended to be called directly by the user. INLINE bool flip_ready() const; diff --git a/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx b/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx index 8ae3c9c8fe..13953a486f 100644 --- a/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx +++ b/panda/src/dxgsg9/wdxGraphicsBuffer9.cxx @@ -54,6 +54,9 @@ wdxGraphicsBuffer9(GraphicsPipe *pipe, // same buffer we draw into. _screenshot_buffer_type = _draw_buffer_type; + _shared_depth_buffer = 0; + _debug = 0; + if (_gsg) { // save to GSG list to handle device lost issues DXGraphicsStateGuardian9 *dxgsg; @@ -79,6 +82,29 @@ wdxGraphicsBuffer9:: dxgsg -> _graphics_buffer_list.remove(this); } + // unshare shared depth buffer if any + this -> unshare_depth_buffer(); + + // unshare all buffers that are sharing this object's depth buffer + { + wdxGraphicsBuffer9 *graphics_buffer; + list ::iterator graphics_buffer_iterator; + + graphics_buffer_iterator = _shared_depth_buffer_list.begin( ); + while (graphics_buffer_iterator != _shared_depth_buffer_list.end( )) { + graphics_buffer = (*graphics_buffer_iterator); + if (graphics_buffer) { + // this call removes the entry from the list + graphics_buffer -> unshare_depth_buffer(); + } + graphics_buffer_iterator = _shared_depth_buffer_list.begin( ); + } + } + + if (_debug) { + printf ("wdxGraphicsBuffer9 destructor \n"); + } + this -> close_buffer ( ); } @@ -147,7 +173,7 @@ end_frame(FrameMode mode, Thread *current_thread) { } //////////////////////////////////////////////////////////////////// -// Function: wglGraphicsStateGuardian::save_bitplanes +// Function: wdxGraphicsBuffer9::save_bitplanes // Access: Public // Description: After rendering, d3d_device will need to be restored // to its initial state. This function saves the state. @@ -170,7 +196,7 @@ save_bitplanes() { } //////////////////////////////////////////////////////////////////// -// Function: wglGraphicsStateGuardian::restore_bitplanes +// Function: wdxGraphicsBuffer9::restore_bitplanes // Access: Public // Description: After rendering, d3d_device will need to be restored // to its initial state. This function restores the state. @@ -200,14 +226,13 @@ restore_bitplanes() { //////////////////////////////////////////////////////////////////// -// Function: wglGraphicsStateGuardian::rebuild_bitplanes +// Function: wdxGraphicsBuffer9::rebuild_bitplanes // Access: Public // Description: If necessary, reallocates (or allocates) the // bitplanes for the buffer. //////////////////////////////////////////////////////////////////// bool wdxGraphicsBuffer9:: rebuild_bitplanes() { - HRESULT hr; Texture *color_tex = 0; Texture *depth_tex = 0; @@ -300,30 +325,51 @@ rebuild_bitplanes() { } } + bool release_depth; + + release_depth = true; if (depth_tex_index < 0) { - // Maintain the backing depth surface. - if ((_depth_backing_store)&& - ((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) { - _depth_backing_store->Release(); - _depth_backing_store = NULL; - } - if (!_depth_backing_store) { - hr = _dxgsg -> _d3d_device -> - CreateDepthStencilSurface (bitplane_x, bitplane_y, _saved_depth_desc.Format, - _saved_depth_desc.MultiSampleType, _saved_depth_desc.MultiSampleQuality, - false, &_depth_backing_store, NULL); - if (!SUCCEEDED(hr)) { - dxgsg9_cat.error ( ) << "CreateDepthStencilSurface " << D3DERRORSTRING(hr) FL; + if (_shared_depth_buffer) { + if (_shared_depth_buffer -> _depth_backing_store) { + if (_debug) { + printf ("SHARE DEPTH BUFFER\n"); + } + depth_surf = _shared_depth_buffer -> _depth_backing_store; + release_depth = false; } } - depth_surf = _depth_backing_store; + if (depth_surf == 0) { + // Maintain the backing depth surface. + if ((_depth_backing_store)&& + ((bitplane_x != _backing_sizex)||(bitplane_y != _backing_sizey))) { + _depth_backing_store->Release(); + _depth_backing_store = NULL; + } + if (!_depth_backing_store) { + hr = _dxgsg -> _d3d_device -> + CreateDepthStencilSurface (bitplane_x, bitplane_y, _saved_depth_desc.Format, + _saved_depth_desc.MultiSampleType, _saved_depth_desc.MultiSampleQuality, + false, &_depth_backing_store, NULL); + if (!SUCCEEDED(hr)) { + dxgsg9_cat.error ( ) << "CreateDepthStencilSurface " << D3DERRORSTRING(hr) FL; + } + } + depth_surf = _depth_backing_store; + } } else { // Maintain the depth texture. if (_depth_backing_store) { _depth_backing_store->Release(); _depth_backing_store = NULL; } - depth_tex = get_texture(depth_tex_index); + + if (_shared_depth_buffer) { + depth_tex = _shared_depth_buffer -> get_texture(depth_tex_index); + } + if (depth_tex == 0) { + depth_tex = get_texture(depth_tex_index); + } + depth_tex->set_x_size(bitplane_x); depth_tex->set_y_size(bitplane_y); depth_tex->set_format(Texture::F_depth_stencil); @@ -374,9 +420,13 @@ rebuild_bitplanes() { if ((color_surf != 0)&&(color_surf != _color_backing_store)) { color_surf->Release(); } - if ((depth_surf != 0)&&(depth_surf != _depth_backing_store)) { - depth_surf->Release(); + + if (release_depth) { + if ((depth_surf != 0)&&(depth_surf != _depth_backing_store)) { + depth_surf->Release(); + } } + return true; } @@ -558,3 +608,108 @@ process_1_event() { // Call window_proc DispatchMessage(&msg); } + + + + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer9::share_depth_buffer +// Access: Published +// Description: Will attempt to use the depth buffer of the input +// graphics_output. The buffer sizes must be exactly +// the same. +//////////////////////////////////////////////////////////////////// +bool wdxGraphicsBuffer9:: +share_depth_buffer(GraphicsOutput *graphics_output) { + + bool state; + wdxGraphicsBuffer9 *input_graphics_output; + + state = false; + input_graphics_output = DCAST (wdxGraphicsBuffer9, graphics_output); + if (this != input_graphics_output && input_graphics_output) { + + state = true; + this -> unshare_depth_buffer(); + + if (_debug) { + printf ("share_depth_buffer\n"); + } + + // check buffer sizes + if (this -> get_x_size() != input_graphics_output -> get_x_size()) { + if (_debug) { + printf ("ERROR: share_depth_buffer: non matching width \n"); + } + state = false; + } + + if (this -> get_y_size() != input_graphics_output -> get_y_size()) { + if (_debug) { + printf ("ERROR: share_depth_buffer: non matching height \n"); + } + state = false; + } + + if (state) { + // let the input GraphicsOutput know that there is an object + // sharing its depth buffer + input_graphics_output -> register_shared_depth_buffer(this); + _shared_depth_buffer = input_graphics_output; + state = true; + } + } + + return state; +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer9::unshare_depth_buffer +// Access: Published +// Description: Discontinue sharing the depth buffer. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer9:: +unshare_depth_buffer() { + if (_shared_depth_buffer) { + if (_debug) { + printf ("wdxGraphicsBuffer9 unshare_depth_buffer \n"); + } + + // let the GraphicsOutput know that this object is no longer + // sharing its depth buffer + _shared_depth_buffer -> unregister_shared_depth_buffer(this); + _shared_depth_buffer = 0; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer9::register_shared_depth_buffer +// Access: Public +// Description: Register/save who is sharing the depth buffer. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer9:: +register_shared_depth_buffer(GraphicsOutput *graphics_output) { + wdxGraphicsBuffer9 *input_graphics_output; + + input_graphics_output = DCAST (wdxGraphicsBuffer9, graphics_output); + if (input_graphics_output) { + // add to list + _shared_depth_buffer_list.push_back(input_graphics_output); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: wdxGraphicsBuffer9::unregister_shared_depth_buffer +// Access: Public +// Description: Unregister who is sharing the depth buffer. +//////////////////////////////////////////////////////////////////// +void wdxGraphicsBuffer9:: +unregister_shared_depth_buffer(GraphicsOutput *graphics_output) { + wdxGraphicsBuffer9 *input_graphics_output; + + input_graphics_output = DCAST (wdxGraphicsBuffer9, graphics_output); + if (input_graphics_output) { + // remove from list + _shared_depth_buffer_list.remove(input_graphics_output); + } +} diff --git a/panda/src/dxgsg9/wdxGraphicsBuffer9.h b/panda/src/dxgsg9/wdxGraphicsBuffer9.h index 5c19fed982..9c4f0be9ac 100644 --- a/panda/src/dxgsg9/wdxGraphicsBuffer9.h +++ b/panda/src/dxgsg9/wdxGraphicsBuffer9.h @@ -51,6 +51,12 @@ public: virtual void select_cube_map(int cube_map_index); virtual void process_events(); + virtual bool share_depth_buffer(GraphicsOutput *graphics_output); + virtual void unshare_depth_buffer(); + + void register_shared_depth_buffer(GraphicsOutput *graphics_output); + void unregister_shared_depth_buffer(GraphicsOutput *graphics_output); + protected: virtual void close_buffer(); virtual bool open_buffer(); @@ -72,6 +78,9 @@ private: int _backing_sizex; int _backing_sizey; + wdxGraphicsBuffer9 *_shared_depth_buffer; + list _shared_depth_buffer_list; + public: static TypeHandle get_class_type() { return _type_handle; @@ -87,6 +96,7 @@ public: virtual TypeHandle force_init_type() {init_type(); return get_class_type();} private: + bool _debug; static TypeHandle _type_handle; friend class DXGraphicsStateGuardian9; diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index 9815b1a27b..2f6982ee90 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -46,6 +46,8 @@ CLP(GraphicsBuffer)(GraphicsPipe *pipe, _rb[i] = 0; _tex[i] = 0; } + + _shared_depth_buffer = 0; } //////////////////////////////////////////////////////////////////// @@ -55,6 +57,24 @@ CLP(GraphicsBuffer)(GraphicsPipe *pipe, //////////////////////////////////////////////////////////////////// CLP(GraphicsBuffer):: ~CLP(GraphicsBuffer)() { + // unshare shared depth buffer if any + this -> unshare_depth_buffer(); + + // unshare all buffers that are sharing this object's depth buffer + { + CLP(GraphicsBuffer) *graphics_buffer; + list ::iterator graphics_buffer_iterator; + + graphics_buffer_iterator = _shared_depth_buffer_list.begin( ); + while (graphics_buffer_iterator != _shared_depth_buffer_list.end( )) { + graphics_buffer = (*graphics_buffer_iterator); + if (graphics_buffer) { + // this call removes the entry from the list + graphics_buffer -> unshare_depth_buffer(); + } + graphics_buffer_iterator = _shared_depth_buffer_list.begin( ); + } + } } //////////////////////////////////////////////////////////////////// @@ -336,7 +356,7 @@ bind_slot(bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum atta // If a renderbuffer is already attached to the slot, and it's // the right size, then no update of this slot is needed. - if ((_rb[slot] != 0)&&(!rb_resize)) { + if (_shared_depth_buffer == 0 && (_rb[slot] != 0)&&(!rb_resize)) { return; } @@ -352,16 +372,33 @@ bind_slot(bool rb_resize, Texture **attach, RenderTexturePlane slot, GLenum atta glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, _rb_size_x, _rb_size_y); glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0); + + GLuint rb; + + rb = _rb[slot]; + if (_shared_depth_buffer) { + rb = _shared_depth_buffer -> _rb[slot]; + } + glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, _rb[slot]); + GL_RENDERBUFFER_EXT, rb); + glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, _rb[slot]); + GL_RENDERBUFFER_EXT, rb); } else { glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, _rb_size_x, _rb_size_y); glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0); + + GLuint rb; + + rb = _rb[slot]; + if (_shared_depth_buffer) { + rb = _shared_depth_buffer -> _rb[slot]; + } + glgsg->_glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, _rb[slot]); + GL_RENDERBUFFER_EXT, rb); } } else { glgsg->_glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA, @@ -577,3 +614,92 @@ close_buffer() { _is_valid = false; } +//////////////////////////////////////////////////////////////////// +// Function: glGraphicsBuffer::share_depth_buffer +// Access: Published +// Description: Will attempt to use the depth buffer of the input +// graphics_output. The buffer sizes must be exactly +// the same. +//////////////////////////////////////////////////////////////////// +bool CLP(GraphicsBuffer):: +share_depth_buffer(GraphicsOutput *graphics_output) { + + bool state; + CLP(GraphicsBuffer) *input_graphics_output; + + state = false; + input_graphics_output = DCAST (CLP(GraphicsBuffer), graphics_output); + if (this != input_graphics_output && input_graphics_output) { + + state = true; + this -> unshare_depth_buffer(); + + // check buffer sizes + if (this -> get_x_size() != input_graphics_output -> get_x_size()) { + GLCAT.error() << "share_depth_buffer: non matching width \n"; + state = false; + } + + if (this -> get_y_size() != input_graphics_output -> get_y_size()) { + GLCAT.error() << "share_depth_buffer: non matching height \n"; + state = false; + } + + if (state) { + // let the input GraphicsOutput know that there is an object + // sharing its depth buffer + input_graphics_output -> register_shared_depth_buffer(this); + _shared_depth_buffer = input_graphics_output; + state = true; + } + } + + return state; +} + +//////////////////////////////////////////////////////////////////// +// Function: glGraphicsBuffer::unshare_depth_buffer +// Access: Published +// Description: Discontinue sharing the depth buffer. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsBuffer):: +unshare_depth_buffer() { + if (_shared_depth_buffer) { + // let the GraphicsOutput know that this object is no longer + // sharing its depth buffer + _shared_depth_buffer -> unregister_shared_depth_buffer(this); + _shared_depth_buffer = 0; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: glGraphicsBuffer::register_shared_depth_buffer +// Access: Public +// Description: Register/save who is sharing the depth buffer. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsBuffer):: +register_shared_depth_buffer(GraphicsOutput *graphics_output) { + CLP(GraphicsBuffer) *input_graphics_output; + + input_graphics_output = DCAST (CLP(GraphicsBuffer), graphics_output); + if (input_graphics_output) { + // add to list + _shared_depth_buffer_list.push_back(input_graphics_output); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: glGraphicsBuffer::unregister_shared_depth_buffer +// Access: Public +// Description: Unregister who is sharing the depth buffer. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsBuffer):: +unregister_shared_depth_buffer(GraphicsOutput *graphics_output) { + CLP(GraphicsBuffer) *input_graphics_output; + + input_graphics_output = DCAST (CLP(GraphicsBuffer), graphics_output); + if (input_graphics_output) { + // remove from list + _shared_depth_buffer_list.remove(input_graphics_output); + } +} diff --git a/panda/src/glstuff/glGraphicsBuffer_src.h b/panda/src/glstuff/glGraphicsBuffer_src.h index 966c20f710..2c4cecc99e 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.h +++ b/panda/src/glstuff/glGraphicsBuffer_src.h @@ -70,6 +70,12 @@ public: virtual void select_cube_map(int cube_map_index); + virtual bool share_depth_buffer(GraphicsOutput *graphics_output); + virtual void unshare_depth_buffer(); + + void register_shared_depth_buffer(GraphicsOutput *graphics_output); + void unregister_shared_depth_buffer(GraphicsOutput *graphics_output); + protected: virtual void close_buffer(); virtual bool open_buffer(); @@ -89,6 +95,9 @@ private: PT(Texture) _tex[RTP_COUNT]; GLuint _rb[RTP_COUNT]; GLenum _attach_point[RTP_COUNT]; + + CLP(GraphicsBuffer) *_shared_depth_buffer; + list _shared_depth_buffer_list; public: static TypeHandle get_class_type() {