Added support for automatic texture scaling by backbuffer ratio on backbuffer resize.

This commit is contained in:
Branimir Karadžić 2015-04-13 18:39:38 -07:00
parent 6878b8de29
commit c01a93e29d
8 changed files with 208 additions and 29 deletions

View File

@ -216,10 +216,10 @@ int _main_(int /*_argc*/, char** /*_argv*/)
lum[4] = bgfx::createFrameBuffer( 1, 1, bgfx::TextureFormat::BGRA8); lum[4] = bgfx::createFrameBuffer( 1, 1, bgfx::TextureFormat::BGRA8);
bgfx::FrameBufferHandle bright; bgfx::FrameBufferHandle bright;
bright = bgfx::createFrameBuffer(width/2, height/2, bgfx::TextureFormat::BGRA8); bright = bgfx::createFrameBuffer(bgfx::BackbufferRatio::Half, bgfx::TextureFormat::BGRA8);
bgfx::FrameBufferHandle blur; bgfx::FrameBufferHandle blur;
blur = bgfx::createFrameBuffer(width/8, height/8, bgfx::TextureFormat::BGRA8); blur = bgfx::createFrameBuffer(bgfx::BackbufferRatio::Eighth, bgfx::TextureFormat::BGRA8);
// Imgui. // Imgui.
imguiCreate(); imguiCreate();
@ -256,15 +256,10 @@ int _main_(int /*_argc*/, char** /*_argv*/)
uint32_t msaa = (reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; uint32_t msaa = (reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT;
bgfx::destroyFrameBuffer(fbh); bgfx::destroyFrameBuffer(fbh);
bgfx::destroyFrameBuffer(bright);
bgfx::destroyFrameBuffer(blur);
fbtextures[0] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, ( (msaa+1)<<BGFX_TEXTURE_RT_MSAA_SHIFT)|BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP); fbtextures[0] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, ( (msaa+1)<<BGFX_TEXTURE_RT_MSAA_SHIFT)|BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP);
fbtextures[1] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_BUFFER_ONLY|( (msaa+1)<<BGFX_TEXTURE_RT_MSAA_SHIFT) ); fbtextures[1] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_BUFFER_ONLY|( (msaa+1)<<BGFX_TEXTURE_RT_MSAA_SHIFT) );
fbh = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); fbh = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true);
bright = bgfx::createFrameBuffer(width/2, height/2, bgfx::TextureFormat::BGRA8);
blur = bgfx::createFrameBuffer(width/8, height/8, bgfx::TextureFormat::BGRA8);
} }
imguiBeginFrame(mouseState.m_mx imguiBeginFrame(mouseState.m_mx

View File

@ -189,6 +189,20 @@ namespace bgfx
}; };
}; };
struct BackbufferRatio
{
enum Enum
{
None,
Equal,
Half,
Quarter,
Eighth,
Sixteenth,
Double,
};
};
static const uint16_t invalidHandle = UINT16_MAX; static const uint16_t invalidHandle = UINT16_MAX;
BGFX_HANDLE(DynamicIndexBufferHandle); BGFX_HANDLE(DynamicIndexBufferHandle);
@ -318,10 +332,9 @@ namespace bgfx
uint16_t maxTextureSize; ///< Maximum texture size. uint16_t maxTextureSize; ///< Maximum texture size.
uint16_t maxViews; ///< Maximum views. uint16_t maxViews; ///< Maximum views.
uint8_t maxFBAttachments; ///< Maximum frame buffer attachments. uint8_t maxFBAttachments; ///< Maximum frame buffer attachments.
uint8_t numGPUs; ///< uint8_t numGPUs; ///< Number of enumerated GPUs.
uint16_t vendorId; ///< Selected GPU vendor id.
uint16_t vendorId; ///< uint16_t deviceId; ///< Selected GPU device id.
uint16_t deviceId; ///<
struct GPU struct GPU
{ {
@ -329,7 +342,7 @@ namespace bgfx
uint16_t deviceId; uint16_t deviceId;
}; };
GPU gpu[4]; ///< GPU gpu[4]; ///< Enumerated GPUs.
/// Supported texture formats. /// Supported texture formats.
/// - `BGFX_CAPS_FORMAT_TEXTURE_NONE` - not supported /// - `BGFX_CAPS_FORMAT_TEXTURE_NONE` - not supported
@ -549,10 +562,10 @@ namespace bgfx
/// ///
void shutdown(); void shutdown();
/// Reset graphic settings. /// Reset graphic settings and back-buffer size.
/// ///
/// @param _width Main window width. /// @param _width Back-buffer width.
/// @param _height Main window height. /// @param _height Back-buffer height.
/// @param _flags /// @param _flags
/// - `BGFX_RESET_NONE` - No reset flags. /// - `BGFX_RESET_NONE` - No reset flags.
/// - `BGFX_RESET_FULLSCREEN` - Not supported yet. /// - `BGFX_RESET_FULLSCREEN` - Not supported yet.
@ -560,6 +573,9 @@ namespace bgfx
/// - `BGFX_RESET_VSYNC` - Enable V-Sync. /// - `BGFX_RESET_VSYNC` - Enable V-Sync.
/// - `BGFX_RESET_CAPTURE` - Begin screen capture. /// - `BGFX_RESET_CAPTURE` - Begin screen capture.
/// ///
/// @attention This call doesn't actually change window size, it just
/// resizes back-buffer. Windowing code has to change window size.
///
/// @attention C99 equivalent is `bgfx_reset`. /// @attention C99 equivalent is `bgfx_reset`.
/// ///
void reset(uint32_t _width, uint32_t _height, uint32_t _flags = BGFX_RESET_NONE); void reset(uint32_t _width, uint32_t _height, uint32_t _flags = BGFX_RESET_NONE);
@ -917,6 +933,9 @@ namespace bgfx
/// ///
TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE, const Memory* _mem = NULL); TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE, const Memory* _mem = NULL);
///
TextureHandle createTexture2D(BackbufferRatio::Enum _ratio, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE);
/// Create 3D texture. /// Create 3D texture.
/// ///
/// @param _width /// @param _width
@ -1013,6 +1032,9 @@ namespace bgfx
/// ///
FrameBufferHandle createFrameBuffer(uint16_t _width, uint16_t _height, TextureFormat::Enum _format, uint32_t _textureFlags = BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP); FrameBufferHandle createFrameBuffer(uint16_t _width, uint16_t _height, TextureFormat::Enum _format, uint32_t _textureFlags = BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP);
///
FrameBufferHandle createFrameBuffer(BackbufferRatio::Enum _ratio, TextureFormat::Enum _format, uint32_t _textureFlags = BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP);
/// Create frame buffer. /// Create frame buffer.
/// ///
/// @param _num Number of texture attachments. /// @param _num Number of texture attachments.

View File

@ -1830,6 +1830,21 @@ again:
} }
break; break;
case CommandBuffer::ResizeTexture:
{
TextureHandle handle;
_cmdbuf.read(handle);
uint16_t width;
_cmdbuf.read(width);
uint16_t height;
_cmdbuf.read(height);
m_renderCtx->resizeTexture(handle, width, height);
}
break;
case CommandBuffer::DestroyTexture: case CommandBuffer::DestroyTexture:
{ {
TextureHandle handle; TextureHandle handle;
@ -2412,10 +2427,28 @@ again:
{ {
BGFX_CHECK_MAIN_THREAD(); BGFX_CHECK_MAIN_THREAD();
BX_CHECK(NULL != _mem, "_mem can't be NULL"); BX_CHECK(NULL != _mem, "_mem can't be NULL");
return s_ctx->createTexture(_mem, _flags, _skip, _info); return s_ctx->createTexture(_mem, _flags, _skip, _info, BackbufferRatio::None);
} }
TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem) void getTextureSizeFromRatio(BackbufferRatio::Enum _ratio, uint16_t& _width, uint16_t& _height)
{
switch (_ratio)
{
case BackbufferRatio::Half: _width /= 2; _height /= 2; break;
case BackbufferRatio::Quarter: _width /= 4; _height /= 4; break;
case BackbufferRatio::Eighth: _width /= 8; _height /= 8; break;
case BackbufferRatio::Sixteenth: _width /= 16; _height /= 16; break;
case BackbufferRatio::Double: _width *= 2; _height *= 2; break;
default:
break;
}
_width = bx::uint16_max(1, _width);
_height = bx::uint16_max(1, _height);
}
TextureHandle createTexture2D(BackbufferRatio::Enum _ratio, uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
{ {
BGFX_CHECK_MAIN_THREAD(); BGFX_CHECK_MAIN_THREAD();
@ -2440,19 +2473,36 @@ again:
uint32_t magic = BGFX_CHUNK_MAGIC_TEX; uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
bx::write(&writer, magic); bx::write(&writer, magic);
if (BackbufferRatio::None != _ratio)
{
_width = uint16_t(s_ctx->m_frame->m_resolution.m_width);
_height = uint16_t(s_ctx->m_frame->m_resolution.m_height);
getTextureSizeFromRatio(_ratio, _width, _height);
}
TextureCreate tc; TextureCreate tc;
tc.m_flags = _flags; tc.m_flags = _flags;
tc.m_width = _width; tc.m_width = _width;
tc.m_height = _height; tc.m_height = _height;
tc.m_sides = 0; tc.m_sides = 0;
tc.m_depth = 0; tc.m_depth = 0;
tc.m_numMips = _numMips; tc.m_numMips = _numMips;
tc.m_format = uint8_t(_format); tc.m_format = uint8_t(_format);
tc.m_cubeMap = false; tc.m_cubeMap = false;
tc.m_mem = _mem; tc.m_mem = _mem;
bx::write(&writer, tc); bx::write(&writer, tc);
return s_ctx->createTexture(mem, _flags, 0, NULL); return s_ctx->createTexture(mem, _flags, 0, NULL, _ratio);
}
TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
{
return createTexture2D(BackbufferRatio::None, _width, _height, _numMips, _format, _flags, _mem);
}
TextureHandle createTexture2D(BackbufferRatio::Enum _ratio, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags)
{
return createTexture2D(_ratio, 0, 0, _numMips, _format, _flags, NULL);
} }
TextureHandle createTexture3D(uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem) TextureHandle createTexture3D(uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
@ -2493,7 +2543,7 @@ again:
tc.m_mem = _mem; tc.m_mem = _mem;
bx::write(&writer, tc); bx::write(&writer, tc);
return s_ctx->createTexture(mem, _flags, 0, NULL); return s_ctx->createTexture(mem, _flags, 0, NULL, BackbufferRatio::None);
} }
TextureHandle createTextureCube(uint16_t _size, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem) TextureHandle createTextureCube(uint16_t _size, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
@ -2533,7 +2583,7 @@ again:
tc.m_mem = _mem; tc.m_mem = _mem;
bx::write(&writer, tc); bx::write(&writer, tc);
return s_ctx->createTexture(mem, _flags, 0, NULL); return s_ctx->createTexture(mem, _flags, 0, NULL, BackbufferRatio::None);
} }
void destroyTexture(TextureHandle _handle) void destroyTexture(TextureHandle _handle)
@ -2596,6 +2646,13 @@ again:
return createFrameBuffer(1, &th, true); return createFrameBuffer(1, &th, true);
} }
FrameBufferHandle createFrameBuffer(BackbufferRatio::Enum _ratio, TextureFormat::Enum _format, uint32_t _textureFlags)
{
_textureFlags |= _textureFlags&BGFX_TEXTURE_RT_MSAA_MASK ? 0 : BGFX_TEXTURE_RT;
TextureHandle th = createTexture2D(_ratio, 1, _format, _textureFlags);
return createFrameBuffer(1, &th, true);
}
FrameBufferHandle createFrameBuffer(uint8_t _num, TextureHandle* _handles, bool _destroyTextures) FrameBufferHandle createFrameBuffer(uint8_t _num, TextureHandle* _handles, bool _destroyTextures)
{ {
BGFX_CHECK_MAIN_THREAD(); BGFX_CHECK_MAIN_THREAD();

View File

@ -305,6 +305,7 @@ namespace bgfx
bool isGraphicsDebuggerPresent(); bool isGraphicsDebuggerPresent();
void release(const Memory* _mem); void release(const Memory* _mem);
const char* getAttribName(Attrib::Enum _attr); const char* getAttribName(Attrib::Enum _attr);
void getTextureSizeFromRatio(BackbufferRatio::Enum _ratio, uint16_t& _width, uint16_t& _height);
inline uint32_t castfu(float _value) inline uint32_t castfu(float _value)
{ {
@ -568,6 +569,7 @@ namespace bgfx
CreateProgram, CreateProgram,
CreateTexture, CreateTexture,
UpdateTexture, UpdateTexture,
ResizeTexture,
CreateFrameBuffer, CreateFrameBuffer,
CreateUniform, CreateUniform,
UpdateViewName, UpdateViewName,
@ -1849,6 +1851,7 @@ namespace bgfx
virtual void updateTextureBegin(TextureHandle _handle, uint8_t _side, uint8_t _mip) = 0; virtual void updateTextureBegin(TextureHandle _handle, uint8_t _side, uint8_t _mip) = 0;
virtual void updateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) = 0; virtual void updateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) = 0;
virtual void updateTextureEnd() = 0; virtual void updateTextureEnd() = 0;
virtual void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height) = 0;
virtual void destroyTexture(TextureHandle _handle) = 0; virtual void destroyTexture(TextureHandle _handle) = 0;
virtual void createFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const TextureHandle* _textureHandles) = 0; virtual void createFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const TextureHandle* _textureHandles) = 0;
virtual void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) = 0; virtual void createFrameBuffer(FrameBufferHandle _handle, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) = 0;
@ -1925,6 +1928,17 @@ namespace bgfx
m_resolution.m_flags = _flags; m_resolution.m_flags = _flags;
memset(m_fb, 0xff, sizeof(m_fb) ); memset(m_fb, 0xff, sizeof(m_fb) );
for (uint16_t ii = 0, num = m_textureHandle.getNumHandles(); ii < num; ++ii)
{
uint16_t textureIdx = m_textureHandle.getHandleAt(ii);
const TextureRef& textureRef = m_textureRef[textureIdx];
if (BackbufferRatio::None != textureRef.m_bbRatio)
{
TextureHandle handle = { textureIdx };
resizeTexture(handle, uint16_t(m_resolution.m_width), uint16_t(m_resolution.m_height) );
}
}
} }
BGFX_API_FUNC(void setDebug(uint32_t _debug) ) BGFX_API_FUNC(void setDebug(uint32_t _debug) )
@ -2723,7 +2737,7 @@ namespace bgfx
} }
} }
BGFX_API_FUNC(TextureHandle createTexture(const Memory* _mem, uint32_t _flags, uint8_t _skip, TextureInfo* _info) ) BGFX_API_FUNC(TextureHandle createTexture(const Memory* _mem, uint32_t _flags, uint8_t _skip, TextureInfo* _info, BackbufferRatio::Enum _ratio) )
{ {
TextureInfo ti; TextureInfo ti;
if (NULL == _info) if (NULL == _info)
@ -2761,6 +2775,7 @@ namespace bgfx
{ {
TextureRef& ref = m_textureRef[handle.idx]; TextureRef& ref = m_textureRef[handle.idx];
ref.m_refCount = 1; ref.m_refCount = 1;
ref.m_bbRatio = uint8_t(_ratio);
ref.m_format = uint8_t(_info->format); ref.m_format = uint8_t(_info->format);
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateTexture); CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateTexture);
@ -2786,6 +2801,26 @@ namespace bgfx
textureDecRef(_handle); textureDecRef(_handle);
} }
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height)
{
const TextureRef& textureRef = m_textureRef[_handle.idx];
BX_CHECK(BackbufferRatio::None != textureRef.m_bbRatio, "");
getTextureSizeFromRatio(BackbufferRatio::Enum(textureRef.m_bbRatio), _width, _height);
BX_TRACE("Resize %3d: %4dx%d %s"
, _handle.idx
, _width
, _height
, getName(TextureFormat::Enum(textureRef.m_format) )
);
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::ResizeTexture);
cmdbuf.write(_handle);
cmdbuf.write(_width);
cmdbuf.write(_height);
}
void textureIncRef(TextureHandle _handle) void textureIncRef(TextureHandle _handle)
{ {
TextureRef& ref = m_textureRef[_handle.idx]; TextureRef& ref = m_textureRef[_handle.idx];
@ -3437,6 +3472,7 @@ namespace bgfx
struct TextureRef struct TextureRef
{ {
int16_t m_refCount; int16_t m_refCount;
uint8_t m_bbRatio;
uint8_t m_format; uint8_t m_format;
}; };

View File

@ -978,6 +978,35 @@ BX_PRAGMA_DIAGNOSTIC_POP();
{ {
} }
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height) BX_OVERRIDE
{
TextureD3D11& texture = m_textures[_handle.idx];
uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate);
const Memory* mem = alloc(size);
bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
bx::write(&writer, magic);
TextureCreate tc;
tc.m_flags = texture.m_flags;
tc.m_width = _width;
tc.m_height = _height;
tc.m_sides = 0;
tc.m_depth = 0;
tc.m_numMips = 1;
tc.m_format = texture.m_requestedFormat;
tc.m_cubeMap = false;
tc.m_mem = NULL;
bx::write(&writer, tc);
texture.destroy();
texture.create(mem, tc.m_flags, 0);
release(mem);
}
void destroyTexture(TextureHandle _handle) BX_OVERRIDE void destroyTexture(TextureHandle _handle) BX_OVERRIDE
{ {
m_textures[_handle.idx].destroy(); m_textures[_handle.idx].destroy();
@ -2462,7 +2491,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx; ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
BX_CHECK(m_dynamic, "Must be dynamic!"); BX_CHECK(m_dynamic, "Must be dynamic!");
#if 1 #if 0
BX_UNUSED(_discard); BX_UNUSED(_discard);
ID3D11Device* device = s_renderD3D11->m_device; ID3D11Device* device = s_renderD3D11->m_device;

View File

@ -774,6 +774,13 @@ namespace bgfx { namespace d3d9
m_updateTexture = NULL; m_updateTexture = NULL;
} }
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height) BX_OVERRIDE
{
TextureD3D9& texture = m_textures[_handle.idx];
texture.m_width = _width;
texture.m_height = _height;
}
void destroyTexture(TextureHandle _handle) BX_OVERRIDE void destroyTexture(TextureHandle _handle) BX_OVERRIDE
{ {
m_textures[_handle.idx].destroy(); m_textures[_handle.idx].destroy();

View File

@ -1717,6 +1717,35 @@ namespace bgfx { namespace gl
{ {
} }
void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height) BX_OVERRIDE
{
TextureGL& texture = m_textures[_handle.idx];
uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate);
const Memory* mem = alloc(size);
bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
bx::write(&writer, magic);
TextureCreate tc;
tc.m_flags = texture.m_flags;
tc.m_width = _width;
tc.m_height = _height;
tc.m_sides = 0;
tc.m_depth = 0;
tc.m_numMips = 1;
tc.m_format = texture.m_requestedFormat;
tc.m_cubeMap = false;
tc.m_mem = NULL;
bx::write(&writer, tc);
texture.destroy();
texture.create(mem, tc.m_flags, 0);
release(mem);
}
void destroyTexture(TextureHandle _handle) BX_OVERRIDE void destroyTexture(TextureHandle _handle) BX_OVERRIDE
{ {
m_textures[_handle.idx].destroy(); m_textures[_handle.idx].destroy();

View File

@ -113,6 +113,10 @@ namespace bgfx { namespace noop
{ {
} }
void resizeTexture(TextureHandle /*_handle*/, uint16_t /*_width*/, uint16_t /*_height*/) BX_OVERRIDE
{
}
void destroyTexture(TextureHandle /*_handle*/) BX_OVERRIDE void destroyTexture(TextureHandle /*_handle*/) BX_OVERRIDE
{ {
} }