diff --git a/examples/07-callback/callback.cpp b/examples/07-callback/callback.cpp index 1789f0cb6..1c4a16d58 100644 --- a/examples/07-callback/callback.cpp +++ b/examples/07-callback/callback.cpp @@ -439,7 +439,8 @@ int _main_(int _argc, char** _argv) // Take screen shot at frame 150. if (150 == frame) { - bgfx::saveScreenShot("temp/frame150"); + bgfx::FrameBufferHandle fbh = BGFX_INVALID_HANDLE; + bgfx::saveScreenShot(fbh, "temp/frame150"); } // Advance to next frame. Rendering thread will be kicked to diff --git a/examples/common/entry/entry.cpp b/examples/common/entry/entry.cpp index 61692ba0b..19237f60f 100644 --- a/examples/common/entry/entry.cpp +++ b/examples/common/entry/entry.cpp @@ -312,9 +312,11 @@ BX_PRAGMA_DIAGNOSTIC_POP(); } else if (0 == bx::strncmp(_argv[1], "screenshot") ) { + bgfx::FrameBufferHandle fbh = BGFX_INVALID_HANDLE; + if (_argc > 2) { - bgfx::saveScreenShot(_argv[2]); + bgfx::saveScreenShot(fbh, _argv[2]); } else { @@ -323,7 +325,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); char filePath[256]; bx::snprintf(filePath, sizeof(filePath), "temp/screenshot-%d", tt); - bgfx::saveScreenShot(filePath); + bgfx::saveScreenShot(fbh, filePath); } return 0; diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index d41ba5915..f41e89ae1 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -2812,6 +2812,7 @@ namespace bgfx /// Request screen shot. /// + /// @param[in] _handle Frame buffer handle. /// @param[in] _filePath Will be passed to `bgfx::CallbackI::screenShot` callback. /// /// @remarks @@ -2819,7 +2820,7 @@ namespace bgfx /// /// @attention C99 equivalent is `bgfx_save_screen_shot`. /// - void saveScreenShot(const char* _filePath); + void saveScreenShot(FrameBufferHandle _handle, const char* _filePath); } // namespace bgfx diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h index addf7f7b3..d9581f945 100644 --- a/include/bgfx/c99/bgfx.h +++ b/include/bgfx/c99/bgfx.h @@ -909,6 +909,6 @@ BGFX_C_API void bgfx_discard(); BGFX_C_API void bgfx_blit(uint8_t _id, bgfx_texture_handle_t _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, bgfx_texture_handle_t _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth); /**/ -BGFX_C_API void bgfx_save_screen_shot(const char* _filePath); +BGFX_C_API void bgfx_save_screen_shot(bgfx_frame_buffer_handle_t _handle, const char* _filePath); #endif // BGFX_C99_H_HEADER_GUARD diff --git a/include/bgfx/c99/platform.h b/include/bgfx/c99/platform.h index 8e44aeea6..62a353ca0 100644 --- a/include/bgfx/c99/platform.h +++ b/include/bgfx/c99/platform.h @@ -198,7 +198,7 @@ typedef struct bgfx_interface_vtbl uint32_t (*dispatch_indirect)(uint8_t _id, bgfx_program_handle_t _handle, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, uint8_t _flags); void (*discard)(); void (*blit)(uint8_t _id, bgfx_texture_handle_t _dst, uint8_t _dstMip, uint16_t _dstX, uint16_t _dstY, uint16_t _dstZ, bgfx_texture_handle_t _src, uint8_t _srcMip, uint16_t _srcX, uint16_t _srcY, uint16_t _srcZ, uint16_t _width, uint16_t _height, uint16_t _depth); - void (*save_screen_shot)(const char* _filePath); + void (*save_screen_shot)(bgfx_frame_buffer_handle_t _handle, const char* _filePath); } bgfx_interface_vtbl_t; diff --git a/include/bgfx/defines.h b/include/bgfx/defines.h index 2776d5a97..373e02eaa 100644 --- a/include/bgfx/defines.h +++ b/include/bgfx/defines.h @@ -6,7 +6,7 @@ #ifndef BGFX_DEFINES_H_HEADER_GUARD #define BGFX_DEFINES_H_HEADER_GUARD -#define BGFX_API_VERSION UINT32_C(36) +#define BGFX_API_VERSION UINT32_C(37) /// #define BGFX_STATE_RGB_WRITE UINT64_C(0x0000000000000001) //!< Enable RGB write. diff --git a/src/bgfx.cpp b/src/bgfx.cpp index cbcc7660a..a68982233 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -2449,12 +2449,15 @@ namespace bgfx case CommandBuffer::SaveScreenShot: { + FrameBufferHandle handle; + _cmdbuf.read(handle); + uint16_t len; _cmdbuf.read(len); const char* filePath = (const char*)_cmdbuf.skip(len); - m_renderCtx->saveScreenShot(filePath); + m_renderCtx->saveScreenShot(handle, filePath); } break; @@ -3844,10 +3847,10 @@ error: s_ctx->blit(_id, _dst, _dstMip, _dstX, _dstY, _dstZ, _src, _srcMip, _srcX, _srcY, _srcZ, _width, _height, _depth); } - void saveScreenShot(const char* _filePath) + void saveScreenShot(FrameBufferHandle _handle, const char* _filePath) { BGFX_CHECK_MAIN_THREAD(); - s_ctx->saveScreenShot(_filePath); + s_ctx->saveScreenShot(_handle, _filePath); } } // namespace bgfx @@ -4775,9 +4778,10 @@ BGFX_C_API void bgfx_blit(uint8_t _id, bgfx_texture_handle_t _dst, uint8_t _dstM bgfx::blit(_id, dst.cpp, _dstMip, _dstX, _dstY, _dstZ, src.cpp, _srcMip, _srcX, _srcY, _srcZ, _width, _height, _depth); } -BGFX_C_API void bgfx_save_screen_shot(const char* _filePath) +BGFX_C_API void bgfx_save_screen_shot(bgfx_frame_buffer_handle _handle, const char* _filePath) { - bgfx::saveScreenShot(_filePath); + union { bgfx_frame_buffer_handle_t c; bgfx::FrameBufferHandle cpp; } handle = { _handle }; + bgfx::saveScreenShot(handle.cpp, _filePath); } BGFX_C_API bgfx_render_frame_t bgfx_render_frame() diff --git a/src/bgfx_p.h b/src/bgfx_p.h index aca9a3a84..987d9d9ad 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -2166,7 +2166,7 @@ namespace bgfx virtual void destroyFrameBuffer(FrameBufferHandle _handle) = 0; virtual void createUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) = 0; virtual void destroyUniform(UniformHandle _handle) = 0; - virtual void saveScreenShot(const char* _filePath) = 0; + virtual void saveScreenShot(FrameBufferHandle _handle, const char* _filePath) = 0; virtual void updateViewName(uint8_t _id, const char* _name) = 0; virtual void updateUniform(uint16_t _loc, const void* _data, uint32_t _size) = 0; virtual void setMarker(const char* _marker, uint32_t _size) = 0; @@ -3625,10 +3625,20 @@ namespace bgfx m_freeOcclusionQueryHandle[m_numFreeOcclusionQueryHandles++] = _handle; } - BGFX_API_FUNC(void saveScreenShot(const char* _filePath) ) + BGFX_API_FUNC(void saveScreenShot(FrameBufferHandle _handle, const char* _filePath) ) { + BGFX_CHECK_HANDLE_INVALID_OK("saveScreenShot", m_frameBufferHandle, _handle); + + if (isValid(_handle) ) + { + FrameBufferRef& ref = m_frameBufferRef[_handle.idx]; + BX_CHECK(ref.m_window, "saveScreenShot can be done only for window frame buffer handles (handle: %d).", _handle.idx); BX_UNUSED(ref); + return; + } + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::SaveScreenShot); uint16_t len = (uint16_t)bx::strnlen(_filePath)+1; + cmdbuf.write(_handle); cmdbuf.write(len); cmdbuf.write(_filePath, len); } diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index c8bde54d8..757526b77 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -1975,16 +1975,21 @@ BX_PRAGMA_DIAGNOSTIC_POP(); m_uniformReg.remove(_handle); } - void saveScreenShot(const char* _filePath) BX_OVERRIDE + void saveScreenShot(FrameBufferHandle _handle, const char* _filePath) BX_OVERRIDE { - if (NULL == m_swapChain) + IDXGISwapChain* swapChain = isValid(_handle) + ? m_frameBuffers[_handle.idx].m_swapChain + : m_swapChain + ; + + if (NULL == swapChain) { BX_TRACE("Unable to capture screenshot %s.", _filePath); return; } ID3D11Texture2D* backBuffer; - DX_CHECK(m_swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); + DX_CHECK(swapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer) ); D3D11_TEXTURE2D_DESC backBufferDesc; backBuffer->GetDesc(&backBufferDesc); diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index e9ba1fa4b..490c3edda 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -1559,8 +1559,10 @@ namespace bgfx { namespace d3d12 m_uniformReg.remove(_handle); } - void saveScreenShot(const char* _filePath) BX_OVERRIDE + void saveScreenShot(FrameBufferHandle _handle, const char* _filePath) BX_OVERRIDE { + BX_UNUSED(_handle); + uint32_t idx = (m_backBufferColorIdx-1) % m_scd.BufferCount; m_cmd.finish(m_backBufferColorFence[idx]); ID3D12Resource* backBuffer = m_backBufferColor[idx]; diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 2fac6faac..45ecdc2c8 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -1129,9 +1129,11 @@ namespace bgfx { namespace d3d9 m_uniformReg.remove(_handle); } - void saveScreenShot(const char* _filePath) BX_OVERRIDE + void saveScreenShot(FrameBufferHandle _handle, const char* _filePath) BX_OVERRIDE { #if BX_PLATFORM_WINDOWS + BX_UNUSED(_handle); + IDirect3DSurface9* surface; D3DDEVICE_CREATION_PARAMETERS dcp; DX_CHECK(m_device->GetCreationParameters(&dcp) ); @@ -1175,6 +1177,8 @@ namespace bgfx { namespace d3d9 DX_CHECK(surface->UnlockRect() ); DX_RELEASE(surface, 0); +#else + BX_UNUSED(_handle, _filePath); #endif // BX_PLATFORM_WINDOWS } diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 95c2a5549..feaf75f5b 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -2523,14 +2523,24 @@ namespace bgfx { namespace gl m_uniformReg.remove(_handle); } - void saveScreenShot(const char* _filePath) BX_OVERRIDE + void saveScreenShot(FrameBufferHandle _handle, const char* _filePath) BX_OVERRIDE { - uint32_t length = m_resolution.m_width*m_resolution.m_height*4; - uint8_t* data = (uint8_t*)BX_ALLOC(g_allocator, length); - + SwapChainGL* swapChain = NULL; uint32_t width = m_resolution.m_width; uint32_t height = m_resolution.m_height; + if (isValid(_handle) ) + { + const FrameBufferGL& frameBuffer = m_frameBuffers[_handle.idx]; + swapChain = frameBuffer.m_swapChain; + width = frameBuffer.m_width; + height = frameBuffer.m_height; + } + m_glctx.makeCurrent(swapChain); + + uint32_t length = width*height*4; + uint8_t* data = (uint8_t*)BX_ALLOC(g_allocator, length); + GL_CHECK(glReadPixels(0 , 0 , width diff --git a/src/renderer_mtl.mm b/src/renderer_mtl.mm index 75c8d2fb3..87ff8719d 100644 --- a/src/renderer_mtl.mm +++ b/src/renderer_mtl.mm @@ -911,10 +911,14 @@ namespace bgfx { namespace mtl } //cmdPost - void saveScreenShot(const char* _filePath) BX_OVERRIDE + void saveScreenShot(FrameBufferHandle _handle, const char* _filePath) BX_OVERRIDE { + BX_UNUSED(_handle); + if (NULL == m_screenshotTarget) + { return; + } m_cmd.kick(false, true); m_commandBuffer = 0; @@ -2938,8 +2942,7 @@ namespace bgfx { namespace mtl { m_cmd.finish(false); - - if ( m_commandBuffer == NULL ) + if (m_commandBuffer == NULL) { m_commandBuffer = m_cmd.alloc(); } @@ -2949,7 +2952,7 @@ namespace bgfx { namespace mtl m_gpuTimer.addHandlers(m_commandBuffer); - if ( m_blitCommandEncoder ) + if (m_blitCommandEncoder) { m_blitCommandEncoder.endEncoding(); m_blitCommandEncoder = 0; @@ -2957,18 +2960,19 @@ namespace bgfx { namespace mtl updateResolution(_render->m_resolution); - if ( m_saveScreenshot || NULL != m_capture ) + if (m_saveScreenshot + || NULL != m_capture) { - if ( m_screenshotTarget ) + if (m_screenshotTarget) { - if ( m_screenshotTarget.width() != m_resolution.m_width || - m_screenshotTarget.height() != m_resolution.m_height ) + if (m_screenshotTarget.width() != m_resolution.m_width + || m_screenshotTarget.height() != m_resolution.m_height) { MTL_RELEASE(m_screenshotTarget); } } - if ( NULL == m_screenshotTarget) + if (NULL == m_screenshotTarget) { m_textureDescriptor.textureType = MTLTextureType2D; m_textureDescriptor.pixelFormat = m_metalLayer.pixelFormat; @@ -2981,13 +2985,16 @@ namespace bgfx { namespace mtl if ( m_iOS9Runtime || m_macOS11Runtime ) { m_textureDescriptor.cpuCacheMode = MTLCPUCacheModeDefaultCache; - m_textureDescriptor.storageMode = (MTLStorageMode)(((BX_ENABLED(BX_PLATFORM_IOS)) ? 0 /* MTLStorageModeShared */ : 1 /*MTLStorageModeManaged*/) - ); - m_textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; + m_textureDescriptor.storageMode = (MTLStorageMode)(BX_ENABLED(BX_PLATFORM_IOS) + ? 0 /* MTLStorageModeShared */ + : 1 /*MTLStorageModeManaged*/ + ); + m_textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; } - m_screenshotTarget = m_device.newTextureWithDescriptor(m_textureDescriptor); + m_screenshotTarget = m_device.newTextureWithDescriptor(m_textureDescriptor); } + m_saveScreenshot = false; } else diff --git a/src/renderer_noop.cpp b/src/renderer_noop.cpp index 4cc401856..9436a4c5f 100644 --- a/src/renderer_noop.cpp +++ b/src/renderer_noop.cpp @@ -177,7 +177,7 @@ namespace bgfx { namespace noop { } - void saveScreenShot(const char* /*_filePath*/) BX_OVERRIDE + void saveScreenShot(FrameBufferHandle /*_handle*/, const char* /*_filePath*/) BX_OVERRIDE { } diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index 43bf2511b..b33cd0398 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -2097,7 +2097,7 @@ VK_IMPORT_DEVICE m_uniforms[_handle.idx] = NULL; } - void saveScreenShot(const char* /*_filePath*/) BX_OVERRIDE + void saveScreenShot(FrameBufferHandle /*_handle*/, const char* /*_filePath*/) BX_OVERRIDE { }