From 877621105d9b3ac398534f0e73bfcd91520172db Mon Sep 17 00:00:00 2001 From: bkaradzic Date: Wed, 5 Feb 2014 23:07:11 -0800 Subject: [PATCH] Added MRT support. --- README.md | 2 - examples/09-hdr/hdr.cpp | 90 +-- examples/14-shadowvolumes/shadowvolumes.cpp | 27 +- .../shadowmaps_simple.cpp | 18 +- examples/16-shadowmaps/shadowmaps.cpp | 111 ++-- examples/common/entry/entry.cpp | 8 +- include/bgfx.h | 132 ++-- src/bgfx.cpp | 104 ++-- src/bgfx_p.h | 169 ++++-- src/config.h | 10 +- src/image.cpp | 42 ++ src/image.h | 3 + src/renderer_d3d11.cpp | 346 ++++++----- src/renderer_d3d11.h | 32 +- src/renderer_d3d9.cpp | 566 +++++++++++------- src/renderer_d3d9.h | 78 +-- src/renderer_gl.cpp | 548 +++++++---------- src/renderer_gl.h | 28 +- src/renderer_null.cpp | 4 +- tools/shaderc/shaderc.cpp | 68 ++- 20 files changed, 1286 insertions(+), 1100 deletions(-) diff --git a/README.md b/README.md index 4a01c6093..aaad5322b 100644 --- a/README.md +++ b/README.md @@ -309,11 +309,9 @@ Converts Wavefront .obj mesh file to format optimal for using with bgfx. Todo ---- - - Multiple render targets. - BlendFuncSeparate and BlendEquationSeparate. - Blit between textures. - Occlusion queries. - - DX11: MSAA. - Fullscreen mode. - ETC2, PVRTC1/2 decoding fallback for targets that don't support it natively. diff --git a/examples/09-hdr/hdr.cpp b/examples/09-hdr/hdr.cpp index 21ed32e07..885259a84 100644 --- a/examples/09-hdr/hdr.cpp +++ b/examples/09-hdr/hdr.cpp @@ -476,20 +476,26 @@ int _main_(int /*_argc*/, char** /*_argv*/) Mesh mesh; mesh.load("meshes/bunny.bin"); - bgfx::RenderTargetHandle rt = bgfx::createRenderTarget(width, height, BGFX_RENDER_TARGET_COLOR_RGBA8|BGFX_RENDER_TARGET_DEPTH_D16); + bgfx::FrameBufferHandle fbh; + bgfx::TextureHandle fbtextures[] = + { + bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, BGFX_TEXTURE_RT), + bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::D16, BGFX_TEXTURE_RT_BUFFER_ONLY), + }; + fbh = bgfx::createFrameBuffer(BX_COUNTOF(fbtextures), fbtextures, true); - bgfx::RenderTargetHandle lum[5]; - lum[0] = bgfx::createRenderTarget(128, 128, BGFX_RENDER_TARGET_COLOR_RGBA8); - lum[1] = bgfx::createRenderTarget( 64, 64, BGFX_RENDER_TARGET_COLOR_RGBA8); - lum[2] = bgfx::createRenderTarget( 16, 16, BGFX_RENDER_TARGET_COLOR_RGBA8); - lum[3] = bgfx::createRenderTarget( 4, 4, BGFX_RENDER_TARGET_COLOR_RGBA8); - lum[4] = bgfx::createRenderTarget( 1, 1, BGFX_RENDER_TARGET_COLOR_RGBA8); + bgfx::FrameBufferHandle lum[5]; + lum[0] = bgfx::createFrameBuffer(128, 128, bgfx::TextureFormat::BGRA8); + lum[1] = bgfx::createFrameBuffer( 64, 64, bgfx::TextureFormat::BGRA8); + lum[2] = bgfx::createFrameBuffer( 16, 16, bgfx::TextureFormat::BGRA8); + lum[3] = bgfx::createFrameBuffer( 4, 4, bgfx::TextureFormat::BGRA8); + lum[4] = bgfx::createFrameBuffer( 1, 1, bgfx::TextureFormat::BGRA8); - bgfx::RenderTargetHandle bright; - bright = bgfx::createRenderTarget(width/2, height/2, BGFX_RENDER_TARGET_COLOR_RGBA8); + bgfx::FrameBufferHandle bright; + bright = bgfx::createFrameBuffer(width/2, height/2, bgfx::TextureFormat::BGRA8); - bgfx::RenderTargetHandle blur; - blur = bgfx::createRenderTarget(width/8, height/8, BGFX_RENDER_TARGET_COLOR_RGBA8); + bgfx::FrameBufferHandle blur; + blur = bgfx::createFrameBuffer(width/8, height/8, bgfx::TextureFormat::BGRA8); FILE* file = fopen("font/droidsans.ttf", "rb"); uint32_t size = (uint32_t)fsize(file); @@ -511,6 +517,7 @@ int _main_(int /*_argc*/, char** /*_argv*/) uint32_t oldWidth = 0; uint32_t oldHeight = 0; + uint32_t oldReset = reset; entry::MouseState mouseState; @@ -518,19 +525,27 @@ int _main_(int /*_argc*/, char** /*_argv*/) while (!entry::processEvents(width, height, debug, reset, &mouseState) ) { - if (oldWidth != width - || oldHeight != height) + if (oldWidth != width + || oldHeight != height + || oldReset != reset) { // Recreate variable size render targets when resolution changes. oldWidth = width; oldHeight = height; - bgfx::destroyRenderTarget(rt); - bgfx::destroyRenderTarget(bright); - bgfx::destroyRenderTarget(blur); + oldReset = reset; - rt = bgfx::createRenderTarget(width, height, BGFX_RENDER_TARGET_COLOR_RGBA8|BGFX_RENDER_TARGET_DEPTH_D16); - bright = bgfx::createRenderTarget(width/2, height/2, BGFX_RENDER_TARGET_COLOR_RGBA8); - blur = bgfx::createRenderTarget(width/8, height/8, BGFX_RENDER_TARGET_COLOR_RGBA8); + uint32_t msaa = (reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + + bgfx::destroyFrameBuffer(fbh); + bgfx::destroyFrameBuffer(bright); + bgfx::destroyFrameBuffer(blur); + + fbtextures[0] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, ( (msaa+1)<m_freeTextureHandle[ii].idx); } - for (uint16_t ii = 0, num = _frame->m_numFreeRenderTargetHandles; ii < num; ++ii) + for (uint16_t ii = 0, num = _frame->m_numFreeFrameBufferHandles; ii < num; ++ii) { - m_renderTargetHandle.free(_frame->m_freeRenderTargetHandle[ii].idx); + m_frameBufferHandle.free(_frame->m_freeFrameBufferHandle[ii].idx); } for (uint16_t ii = 0, num = _frame->m_numFreeUniformHandles; ii < num; ++ii) @@ -1089,7 +1090,7 @@ namespace bgfx freeDynamicBuffers(); m_submit->m_resolution = m_resolution; m_submit->m_debug = m_debug; - memcpy(m_submit->m_rt, m_rt, sizeof(m_rt) ); + memcpy(m_submit->m_fb, m_fb, sizeof(m_fb) ); memcpy(m_submit->m_clear, m_clear, sizeof(m_clear) ); memcpy(m_submit->m_rect, m_rect, sizeof(m_rect) ); memcpy(m_submit->m_scissor, m_scissor, sizeof(m_scissor) ); @@ -1533,12 +1534,11 @@ namespace bgfx uint8_t mip; _cmdbuf.read(mip); - _cmdbuf.skip(sizeof(Rect) - + sizeof(uint16_t) - + sizeof(uint16_t) - + sizeof(uint16_t) - + sizeof(Memory*) - ); + _cmdbuf.skip(); + _cmdbuf.skip(); + _cmdbuf.skip(); + _cmdbuf.skip(); + _cmdbuf.skip(); uint32_t key = (handle.idx<<16) | (side<<8) @@ -1558,33 +1558,30 @@ namespace bgfx } break; - case CommandBuffer::CreateRenderTarget: + case CommandBuffer::CreateFrameBuffer: { - RenderTargetHandle handle; + FrameBufferHandle handle; _cmdbuf.read(handle); - uint16_t width; - _cmdbuf.read(width); + uint8_t num; + _cmdbuf.read(num); - uint16_t height; - _cmdbuf.read(height); + TextureHandle textureHandles[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; + for (uint32_t ii = 0; ii < num; ++ii) + { + _cmdbuf.read(textureHandles[ii]); + } - uint32_t flags; - _cmdbuf.read(flags); - - uint32_t textureFlags; - _cmdbuf.read(textureFlags); - - rendererCreateRenderTarget(handle, width, height, flags, textureFlags); + rendererCreateFrameBuffer(handle, num, textureHandles); } break; - case CommandBuffer::DestroyRenderTarget: + case CommandBuffer::DestroyFrameBuffer: { - RenderTargetHandle handle; + FrameBufferHandle handle; _cmdbuf.read(handle); - rendererDestroyRenderTarget(handle); + rendererDestroyFrameBuffer(handle); } break; @@ -1647,7 +1644,7 @@ namespace bgfx break; default: - BX_CHECK(false, "WTF!"); + BX_CHECK(false, "Invalid command: %d", command); break; } } while (!end); @@ -1876,11 +1873,10 @@ namespace bgfx _width = bx::uint32_max(1, _width); _height = bx::uint32_max(1, _height); _depth = bx::uint32_max(1, _depth); - _numMips = bx::uint32_max(1, _numMips); - uint32_t width = _width; + uint32_t width = _width; uint32_t height = _height; - uint32_t depth = _depth; + uint32_t depth = _depth; uint32_t bpp = getBitsPerPixel(_format); uint32_t size = 0; @@ -1918,6 +1914,8 @@ namespace bgfx { BGFX_CHECK_MAIN_THREAD(); + _numMips = bx::uint32_max(1, _numMips); + #if BGFX_CONFIG_DEBUG if (NULL != _mem) { @@ -1958,6 +1956,8 @@ namespace bgfx BGFX_CHECK_MAIN_THREAD(); BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_TEXTURE_3D), "Texture3D is not supported! Use bgfx::getCaps to check backend renderer capabilities."); + _numMips = bx::uint32_max(1, _numMips); + #if BGFX_CONFIG_DEBUG if (NULL != _mem) { @@ -1997,6 +1997,8 @@ namespace bgfx { BGFX_CHECK_MAIN_THREAD(); + _numMips = bx::uint32_max(1, _numMips); + #if BGFX_CONFIG_DEBUG if (NULL != _mem) { @@ -2085,17 +2087,33 @@ namespace bgfx } } - RenderTargetHandle createRenderTarget(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) + FrameBufferHandle createFrameBuffer(uint16_t _width, uint16_t _height, TextureFormat::Enum _format, uint32_t _textureFlags) { - BGFX_CHECK_MAIN_THREAD(); - BX_WARN(0 != _width && 0 != _height, "Render target resolution width or height cannot be 0 (width %d, height %d).", _width, _height); - return s_ctx->createRenderTarget(bx::uint16_max(1, _width), bx::uint16_max(1, _height), _flags, _textureFlags); + _textureFlags |= _textureFlags&BGFX_TEXTURE_RT_MSAA_MASK ? 0 : BGFX_TEXTURE_RT; + TextureHandle th = createTexture2D(_width, _height, 1, _format, _textureFlags); + return createFrameBuffer(1, &th, true); } - void destroyRenderTarget(RenderTargetHandle _handle) + FrameBufferHandle createFrameBuffer(uint8_t _num, TextureHandle* _handles, bool _destroyTextures) { BGFX_CHECK_MAIN_THREAD(); - s_ctx->destroyRenderTarget(_handle); + BX_CHECK(NULL != _handles, "_handles can't be NULL"); + FrameBufferHandle handle = s_ctx->createFrameBuffer(_num, _handles); + if (_destroyTextures) + { + for (uint32_t ii = 0; ii < _num; ++ii) + { + destroyTexture(_handles[ii]); + } + } + + return handle; + } + + void destroyFrameBuffer(FrameBufferHandle _handle) + { + BGFX_CHECK_MAIN_THREAD(); + s_ctx->destroyFrameBuffer(_handle); } UniformHandle createUniform(const char* _name, UniformType::Enum _type, uint16_t _num) @@ -2164,16 +2182,16 @@ namespace bgfx s_ctx->setViewSeqMask(_viewMask, _enabled); } - void setViewRenderTarget(uint8_t _id, RenderTargetHandle _handle) + void setViewFrameBuffer(uint8_t _id, FrameBufferHandle _handle) { BGFX_CHECK_MAIN_THREAD(); - s_ctx->setViewRenderTarget(_id, _handle); + s_ctx->setViewFrameBuffer(_id, _handle); } - void setViewRenderTargetMask(uint32_t _mask, RenderTargetHandle _handle) + void setViewFrameBufferMask(uint32_t _mask, FrameBufferHandle _handle) { BGFX_CHECK_MAIN_THREAD(); - s_ctx->setViewRenderTargetMask(_mask, _handle); + s_ctx->setViewFrameBufferMask(_mask, _handle); } void setViewTransform(uint8_t _id, const void* _view, const void* _proj, uint8_t _other) @@ -2293,10 +2311,10 @@ namespace bgfx s_ctx->setTexture(_stage, _sampler, _handle, _flags); } - void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth, uint32_t _flags) + void setTexture(uint8_t _stage, UniformHandle _sampler, FrameBufferHandle _handle, uint8_t _attachment, uint32_t _flags) { BGFX_CHECK_MAIN_THREAD(); - s_ctx->setTexture(_stage, _sampler, _handle, _depth, _flags); + s_ctx->setTexture(_stage, _sampler, _handle, _attachment, _flags); } uint32_t submit(uint8_t _id, int32_t _depth) diff --git a/src/bgfx_p.h b/src/bgfx_p.h index f5ae2e5fe..11ff4f9f0 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -139,8 +139,6 @@ namespace stl #define BGFX_SAMPLER_DEFAULT_FLAGS UINT32_C(0x10000000) #define BGFX_SAMPLER_TEXTURE UINT32_C(0x00000000) -#define BGFX_SAMPLER_RENDERTARGET_COLOR UINT32_C(0x40000000) -#define BGFX_SAMPLER_RENDERTARGET_DEPTH UINT32_C(0x80000000) #define BGFX_SAMPLER_TYPE_MASK UINT32_C(0xc0000000) #if BGFX_CONFIG_RENDERER_DIRECT3D9 @@ -512,7 +510,7 @@ namespace bgfx CreateProgram, CreateTexture, UpdateTexture, - CreateRenderTarget, + CreateFrameBuffer, CreateUniform, UpdateViewName, End, @@ -526,7 +524,7 @@ namespace bgfx DestroyFragmentShader, DestroyProgram, DestroyTexture, - DestroyRenderTarget, + DestroyFrameBuffer, DestroyUniform, SaveScreenShot, }; @@ -542,6 +540,7 @@ namespace bgfx template void write(const Type& _in) { + align(BX_ALIGNOF(Type) ); write(reinterpret_cast(&_in), sizeof(Type) ); } @@ -555,6 +554,7 @@ namespace bgfx template void read(Type& _in) { + align(BX_ALIGNOF(Type) ); read(reinterpret_cast(&_in), sizeof(Type) ); } @@ -566,6 +566,20 @@ namespace bgfx return result; } + template + void skip() + { + align(BX_ALIGNOF(Type) ); + skip(sizeof(Type) ); + } + + void align(uint32_t _alignment) + { + const uint32_t mask = _alignment-1; + const uint32_t pos = (m_pos+mask) & (~mask); + m_pos = pos; + } + void reset() { m_pos = 0; @@ -1176,23 +1190,6 @@ namespace bgfx } } - void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth, uint32_t _flags) - { - m_flags |= BGFX_STATE_TEX0<<_stage; - Sampler& sampler = m_state.m_sampler[_stage]; - sampler.m_idx = _handle.idx; - sampler.m_flags = 0 - | (_depth ? BGFX_SAMPLER_RENDERTARGET_DEPTH : BGFX_SAMPLER_RENDERTARGET_COLOR) - | ( (_flags&BGFX_SAMPLER_TYPE_MASK) ? BGFX_SAMPLER_DEFAULT_FLAGS : _flags) - ; - - if (isValid(_sampler) ) - { - uint32_t stage = _stage; - setUniform(_sampler, &stage); - } - } - void discard() { m_discard = false; @@ -1287,10 +1284,10 @@ namespace bgfx ++m_numFreeTextureHandles; } - void free(RenderTargetHandle _handle) + void free(FrameBufferHandle _handle) { - m_freeRenderTargetHandle[m_numFreeRenderTargetHandles] = _handle; - ++m_numFreeRenderTargetHandles; + m_freeFrameBufferHandle[m_numFreeFrameBufferHandles] = _handle; + ++m_numFreeFrameBufferHandles; } void free(UniformHandle _handle) @@ -1309,13 +1306,13 @@ namespace bgfx m_numFreeFragmentShaderHandles = 0; m_numFreeProgramHandles = 0; m_numFreeTextureHandles = 0; - m_numFreeRenderTargetHandles = 0; + m_numFreeFrameBufferHandles = 0; m_numFreeUniformHandles = 0; } SortKey m_key; - RenderTargetHandle m_rt[BGFX_CONFIG_MAX_VIEWS]; + FrameBufferHandle m_fb[BGFX_CONFIG_MAX_VIEWS]; Clear m_clear[BGFX_CONFIG_MAX_VIEWS]; Rect m_rect[BGFX_CONFIG_MAX_VIEWS]; Rect m_scissor[BGFX_CONFIG_MAX_VIEWS]; @@ -1356,7 +1353,7 @@ namespace bgfx uint16_t m_numFreeFragmentShaderHandles; uint16_t m_numFreeProgramHandles; uint16_t m_numFreeTextureHandles; - uint16_t m_numFreeRenderTargetHandles; + uint16_t m_numFreeFrameBufferHandles; uint16_t m_numFreeUniformHandles; IndexBufferHandle m_freeIndexBufferHandle[BGFX_CONFIG_MAX_INDEX_BUFFERS]; @@ -1366,7 +1363,7 @@ namespace bgfx FragmentShaderHandle m_freeFragmentShaderHandle[BGFX_CONFIG_MAX_FRAGMENT_SHADERS]; ProgramHandle m_freeProgramHandle[BGFX_CONFIG_MAX_PROGRAMS]; TextureHandle m_freeTextureHandle[BGFX_CONFIG_MAX_TEXTURES]; - RenderTargetHandle m_freeRenderTargetHandle[BGFX_CONFIG_MAX_RENDER_TARGETS]; + FrameBufferHandle m_freeFrameBufferHandle[BGFX_CONFIG_MAX_FRAME_BUFFERS]; UniformHandle m_freeUniformHandle[BGFX_CONFIG_MAX_UNIFORMS]; TextVideoMem* m_textVideoMem; @@ -1601,7 +1598,7 @@ namespace bgfx m_resolution.m_height = bx::uint32_max(1, _height); m_resolution.m_flags = _flags; - memset(m_rt, 0xff, sizeof(m_rt) ); + memset(m_fb, 0xff, sizeof(m_fb) ); } BGFX_API_FUNC(void setDebug(uint32_t _debug) ) @@ -2185,6 +2182,9 @@ namespace bgfx BX_WARN(isValid(handle), "Failed to allocate texture handle."); if (isValid(handle) ) { + TextureRef& ref = m_textureRef[handle.idx]; + ref.m_refCount = 1; + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateTexture); cmdbuf.write(handle); cmdbuf.write(_mem); @@ -2196,9 +2196,31 @@ namespace bgfx BGFX_API_FUNC(void destroyTexture(TextureHandle _handle) ) { - CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyTexture); - cmdbuf.write(_handle); - m_submit->free(_handle); + if (!isValid(_handle) ) + { + BX_WARN(false, "Passing invalid texture handle to bgfx::destroyTexture"); + return; + } + + textureDecRef(_handle); + } + + void textureIncRef(TextureHandle _handle) + { + TextureRef& ref = m_textureRef[_handle.idx]; + ++ref.m_refCount; + } + + void textureDecRef(TextureHandle _handle) + { + TextureRef& ref = m_textureRef[_handle.idx]; + int32_t refs = --ref.m_refCount; + if (0 == refs) + { + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyTexture); + cmdbuf.write(_handle); + m_submit->free(_handle); + } } BGFX_API_FUNC(void updateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _z, uint16_t _width, uint16_t _height, uint16_t _depth, uint16_t _pitch, const Memory* _mem) ) @@ -2219,29 +2241,48 @@ namespace bgfx cmdbuf.write(_mem); } - BGFX_API_FUNC(RenderTargetHandle createRenderTarget(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) ) + BGFX_API_FUNC(FrameBufferHandle createFrameBuffer(uint8_t _num, TextureHandle* _handles) ) { - RenderTargetHandle handle = { m_renderTargetHandle.alloc() }; + FrameBufferHandle handle = { m_frameBufferHandle.alloc() }; BX_WARN(isValid(handle), "Failed to allocate render target handle."); if (isValid(handle) ) { - CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateRenderTarget); + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::CreateFrameBuffer); cmdbuf.write(handle); - cmdbuf.write(_width); - cmdbuf.write(_height); - cmdbuf.write(_flags); - cmdbuf.write(_textureFlags); + cmdbuf.write(_num); + + FrameBufferRef& ref = m_frameBufferRef[handle.idx]; + memset(ref.m_th, 0xff, sizeof(ref.m_th) ); + for (uint32_t ii = 0; ii < _num; ++ii) + { + TextureHandle handle = _handles[ii]; + + cmdbuf.write(handle); + + ref.m_th[ii] = handle; + textureIncRef(handle); + } } return handle; } - BGFX_API_FUNC(void destroyRenderTarget(RenderTargetHandle _handle) ) + BGFX_API_FUNC(void destroyFrameBuffer(FrameBufferHandle _handle) ) { - CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyRenderTarget); + CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::DestroyFrameBuffer); cmdbuf.write(_handle); m_submit->free(_handle); + + FrameBufferRef& ref = m_frameBufferRef[_handle.idx]; + for (uint32_t ii = 0; ii < BX_COUNTOF(ref.m_th); ++ii) + { + TextureHandle th = ref.m_th[ii]; + if (isValid(th) ) + { + textureDecRef(th); + } + } } BGFX_API_FUNC(UniformHandle createUniform(const char* _name, UniformType::Enum _type, uint16_t _num) ) @@ -2394,19 +2435,19 @@ namespace bgfx } } - BGFX_API_FUNC(void setViewRenderTarget(uint8_t _id, RenderTargetHandle _handle) ) + BGFX_API_FUNC(void setViewFrameBuffer(uint8_t _id, FrameBufferHandle _handle) ) { - m_rt[_id] = _handle; + m_fb[_id] = _handle; } - BGFX_API_FUNC(void setViewRenderTargetMask(uint32_t _viewMask, RenderTargetHandle _handle) ) + BGFX_API_FUNC(void setViewFrameBufferMask(uint32_t _viewMask, FrameBufferHandle _handle) ) { for (uint32_t view = 0, viewMask = _viewMask, ntz = bx::uint32_cnttz(_viewMask); 0 != viewMask; viewMask >>= 1, view += 1, ntz = bx::uint32_cnttz(viewMask) ) { viewMask >>= ntz; view += ntz; - m_rt[view] = _handle; + m_fb[view] = _handle; } } @@ -2540,9 +2581,17 @@ namespace bgfx m_submit->setTexture(_stage, _sampler, _handle, _flags); } - BGFX_API_FUNC(void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth, uint32_t _flags) ) + BGFX_API_FUNC(void setTexture(uint8_t _stage, UniformHandle _sampler, FrameBufferHandle _handle, uint8_t _attachment, uint32_t _flags) ) { - m_submit->setTexture(_stage, _sampler, _handle, _depth, _flags); + BX_CHECK(_attachment < g_caps.maxFBAttachments, "Frame buffer attachment index %d is invalid.", _attachment); + TextureHandle textureHandle = BGFX_INVALID_HANDLE; + if (isValid(_handle) ) + { + textureHandle = m_frameBufferRef[_handle.idx].m_th[_attachment]; + BX_CHECK(isValid(textureHandle), "Frame buffer texture %d is invalid.", _attachment); + } + + m_submit->setTexture(_stage, _sampler, textureHandle, _flags); } BGFX_API_FUNC(uint32_t submit(uint8_t _id, int32_t _depth) ) @@ -2596,8 +2645,8 @@ namespace bgfx void rendererUpdateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void rendererUpdateTextureEnd(); void rendererDestroyTexture(TextureHandle _handle); - void rendererCreateRenderTarget(RenderTargetHandle _handle, uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags); - void rendererDestroyRenderTarget(RenderTargetHandle _handle); + void rendererCreateFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const TextureHandle* _textureHandles); + void rendererDestroyFrameBuffer(FrameBufferHandle _handle); void rendererCreateUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name); void rendererDestroyUniform(UniformHandle _handle); void rendererSaveScreenShot(const char* _filePath); @@ -2685,19 +2734,19 @@ namespace bgfx bx::HandleAllocT m_fragmentShaderHandle; bx::HandleAllocT m_programHandle; bx::HandleAllocT m_textureHandle; - bx::HandleAllocT m_renderTargetHandle; + bx::HandleAllocT m_frameBufferHandle; bx::HandleAllocT m_uniformHandle; struct FragmentShaderRef { - int32_t m_refCount; uint32_t m_inputHash; + int16_t m_refCount; }; struct VertexShaderRef { - int32_t m_refCount; uint32_t m_outputHash; + int16_t m_refCount; }; struct ProgramRef @@ -2708,9 +2757,19 @@ namespace bgfx struct UniformRef { - int32_t m_refCount; UniformType::Enum m_type; uint16_t m_num; + int16_t m_refCount; + }; + + struct TextureRef + { + int16_t m_refCount; + }; + + struct FrameBufferRef + { + TextureHandle m_th[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; }; typedef stl::unordered_map UniformHashMap; @@ -2719,9 +2778,11 @@ namespace bgfx VertexShaderRef m_vertexShaderRef[BGFX_CONFIG_MAX_VERTEX_SHADERS]; FragmentShaderRef m_fragmentShaderRef[BGFX_CONFIG_MAX_FRAGMENT_SHADERS]; ProgramRef m_programRef[BGFX_CONFIG_MAX_PROGRAMS]; + TextureRef m_textureRef[BGFX_CONFIG_MAX_TEXTURES]; + FrameBufferRef m_frameBufferRef[BGFX_CONFIG_MAX_FRAME_BUFFERS]; VertexDeclRef m_declRef; - RenderTargetHandle m_rt[BGFX_CONFIG_MAX_VIEWS]; + FrameBufferHandle m_fb[BGFX_CONFIG_MAX_VIEWS]; Clear m_clear[BGFX_CONFIG_MAX_VIEWS]; Rect m_rect[BGFX_CONFIG_MAX_VIEWS]; Rect m_scissor[BGFX_CONFIG_MAX_VIEWS]; diff --git a/src/config.h b/src/config.h index 4541cf48d..9dd1c6e07 100644 --- a/src/config.h +++ b/src/config.h @@ -188,9 +188,13 @@ # define BGFX_CONFIG_MAX_TEXTURES (4<<10) #endif // BGFX_CONFIG_MAX_TEXTURES -#ifndef BGFX_CONFIG_MAX_RENDER_TARGETS -# define BGFX_CONFIG_MAX_RENDER_TARGETS 64 -#endif // BGFX_CONFIG_MAX_RENDER_TARGETS +#ifndef BGFX_CONFIG_MAX_FRAME_BUFFERS +# define BGFX_CONFIG_MAX_FRAME_BUFFERS 64 +#endif // BGFX_CONFIG_MAX_FRAME_BUFFERS + +#ifndef BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS +# define BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS 4 +#endif // BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS #ifndef BGFX_CONFIG_MAX_UNIFORMS # define BGFX_CONFIG_MAX_UNIFORMS 512 diff --git a/src/image.cpp b/src/image.cpp index 478e7f46d..e8ed9ed81 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -47,6 +47,43 @@ namespace bgfx 8, // D0S8 }; + static const char* s_textureFormatName[TextureFormat::Count] = + { + "BC1", // BC1 + "BC2", // BC2 + "BC3", // BC3 + "BC4", // BC4 + "BC5", // BC5 + "ETC1", // ETC1 + "ETC2", // ETC2 + "ETC2A", // ETC2A + "ETC2A1", // ETC2A1 + "PTC12", // PTC12 + "PTC14", // PTC14 + "PTC12A", // PTC12A + "PTC14A", // PTC14A + "PTC22", // PTC22 + "PTC24", // PTC24 + "", // Unknown + "L8", // L8 + "BGRA8", // BGRA8 + "RGBA16", // RGBA16 + "RGBA16F", // RGBA16F + "R5G6B5", // R5G6B5 + "RGBA4", // RGBA4 + "RGB5A1", // RGB5A1 + "RGB10A2", // RGB10A2 + "", // UnknownDepth + "D16", // D16 + "D24", // D24 + "D24S8", // D24S8 + "D32", // D32 + "D16F", // D16F + "D24F", // D24F + "D32F", // D32F + "D0S8", // D0S8 + }; + bool isCompressed(TextureFormat::Enum _format) { return _format < TextureFormat::Unknown; @@ -71,6 +108,11 @@ namespace bgfx return s_bitsPerPixel[_format]; } + const char* getName(TextureFormat::Enum _format) + { + return s_textureFormatName[_format]; + } + void imageSolid(uint32_t _width, uint32_t _height, uint32_t _solid, void* _dst) { uint32_t* dst = (uint32_t*)_dst; diff --git a/src/image.h b/src/image.h index 0c4bfc2ee..61215d4b0 100644 --- a/src/image.h +++ b/src/image.h @@ -51,6 +51,9 @@ namespace bgfx /// uint32_t getBitsPerPixel(TextureFormat::Enum _format); + /// + const char* getName(TextureFormat::Enum _format); + /// void imageSolid(uint32_t _width, uint32_t _height, uint32_t _solid, void* _dst); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 5e73758a9..cf2a7ec86 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -187,6 +187,8 @@ namespace bgfx struct TextureFormatInfo { DXGI_FORMAT m_fmt; + DXGI_FORMAT m_fmtSrv; + DXGI_FORMAT m_fmtDsv; }; #ifndef DXGI_FORMAT_B4G4R4A4_UNORM @@ -198,39 +200,39 @@ namespace bgfx static const TextureFormatInfo s_textureFormat[TextureFormat::Count] = { - { DXGI_FORMAT_BC1_UNORM }, // BC1 - { DXGI_FORMAT_BC2_UNORM }, // BC2 - { DXGI_FORMAT_BC3_UNORM }, // BC3 - { DXGI_FORMAT_BC4_UNORM }, // BC4 - { DXGI_FORMAT_BC5_UNORM }, // BC5 - { DXGI_FORMAT_UNKNOWN }, // ETC1 - { DXGI_FORMAT_UNKNOWN }, // ETC2 - { DXGI_FORMAT_UNKNOWN }, // ETC2A - { DXGI_FORMAT_UNKNOWN }, // ETC2A1 - { DXGI_FORMAT_UNKNOWN }, // PTC12 - { DXGI_FORMAT_UNKNOWN }, // PTC14 - { DXGI_FORMAT_UNKNOWN }, // PTC12A - { DXGI_FORMAT_UNKNOWN }, // PTC14A - { DXGI_FORMAT_UNKNOWN }, // PTC22 - { DXGI_FORMAT_UNKNOWN }, // PTC24 - { DXGI_FORMAT_UNKNOWN }, // Unknown - { DXGI_FORMAT_R8_UNORM }, // L8 - { DXGI_FORMAT_B8G8R8A8_UNORM }, // BGRA8 - { DXGI_FORMAT_R16G16B16A16_UNORM }, // RGBA16 - { DXGI_FORMAT_R16G16B16A16_FLOAT }, // RGBA16F - { DXGI_FORMAT_B5G6R5_UNORM }, // R5G6B5 - { DXGI_FORMAT_B4G4R4A4_UNORM }, // RGBA4 - { DXGI_FORMAT_B5G5R5A1_UNORM }, // RGB5A1 - { DXGI_FORMAT_R10G10B10A2_UNORM }, // RGB10A2 - { DXGI_FORMAT_UNKNOWN }, // UnknownDepth - { DXGI_FORMAT_D16_UNORM }, // D16 - { DXGI_FORMAT_D24_UNORM_S8_UINT }, // D24 - { DXGI_FORMAT_D24_UNORM_S8_UINT }, // D24S8 - { DXGI_FORMAT_D24_UNORM_S8_UINT }, // D32 - { DXGI_FORMAT_D32_FLOAT, }, // D16F - { DXGI_FORMAT_D32_FLOAT, }, // D24F - { DXGI_FORMAT_D32_FLOAT, }, // D32F - { DXGI_FORMAT_D24_UNORM_S8_UINT }, // D0S8 + { DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN }, // BC1 + { DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN }, // BC2 + { DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN }, // BC3 + { DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_UNKNOWN }, // BC4 + { DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_UNKNOWN }, // BC5 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ETC1 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ETC2 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ETC2A + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ETC2A1 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PTC12 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PTC14 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PTC12A + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PTC14A + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PTC22 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PTC24 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // Unknown + { DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN }, // L8 + { DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN }, // BGRA8 + { DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_UNKNOWN }, // RGBA16 + { DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN }, // RGBA16F + { DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_UNKNOWN }, // R5G6B5 + { DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_UNKNOWN }, // RGBA4 + { DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_UNKNOWN }, // RGB5A1 + { DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN }, // RGB10A2 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // UnknownDepth + { DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_D16_UNORM }, // D16 + { DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT }, // D24 + { DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT }, // D24S8 + { DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT }, // D32 + { DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT }, // D16F + { DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT }, // D24F + { DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT }, // D32F + { DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT }, // D0S8 }; static const D3D11_INPUT_ELEMENT_DESC s_attrib[Attrib::Count] = @@ -352,9 +354,12 @@ namespace bgfx : m_captureTexture(NULL) , m_captureResolve(NULL) , m_wireframe(false) + , m_flags(BGFX_RESET_NONE) , m_vsChanges(0) , m_fsChanges(0) + , m_rtMsaa(false) { + m_fbh.idx = invalidHandle; } void init() @@ -513,12 +518,13 @@ namespace bgfx | BGFX_CAPS_TEXTURE_FORMAT_BC5 | BGFX_CAPS_INSTANCING | BGFX_CAPS_TEXTURE_3D - | BGFX_CAPS_TEXTURE_DEPTH_MASK | BGFX_CAPS_VERTEX_ATTRIB_HALF | BGFX_CAPS_FRAGMENT_DEPTH ); - g_caps.maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + g_caps.maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + g_caps.maxFBAttachments = bx::uint32_min(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS); + updateMsaa(); postReset(); } @@ -555,11 +561,6 @@ namespace bgfx m_textures[ii].destroy(); } - for (uint32_t ii = 0; ii < BX_COUNTOF(m_renderTargets); ++ii) - { - m_renderTargets[ii].destroy(); - } - for (uint32_t ii = 0; ii < BX_COUNTOF(m_uniforms); ++ii) { m_uniforms[ii].destroy(); @@ -744,13 +745,13 @@ namespace bgfx } } - void setRenderTarget(RenderTargetHandle _rt, bool _msaa = true) + void setFrameBuffer(FrameBufferHandle _fbh, bool _msaa = true) { BX_UNUSED(_msaa); - if (!isValid(_rt) ) + if (!isValid(_fbh) ) { m_deviceCtx->OMSetRenderTargets(1, &m_backBufferColor, m_backBufferDepthStencil); - + m_currentColor = m_backBufferColor; m_currentDepthStencil = m_backBufferDepthStencil; } @@ -758,12 +759,23 @@ namespace bgfx { invalidateTextureStage(); - RenderTarget& renderTarget = m_renderTargets[_rt.idx]; - m_deviceCtx->OMSetRenderTargets(1, &renderTarget.m_rtv, renderTarget.m_dsv); + FrameBuffer& frameBuffer = m_frameBuffers[_fbh.idx]; + m_deviceCtx->OMSetRenderTargets(frameBuffer.m_num, frameBuffer.m_rtv, frameBuffer.m_dsv); - m_currentColor = renderTarget.m_rtv; - m_currentDepthStencil = renderTarget.m_dsv; + m_currentColor = frameBuffer.m_rtv[0]; + m_currentDepthStencil = frameBuffer.m_dsv; } + + if (isValid(m_fbh) + && m_fbh.idx != _fbh.idx + && m_rtMsaa) + { + FrameBuffer& frameBuffer = m_frameBuffers[m_fbh.idx]; + frameBuffer.resolve(); + } + + m_fbh = _fbh; + m_rtMsaa = _msaa; } void clear(const Clear& _clear) @@ -1200,7 +1212,7 @@ namespace bgfx Program m_program[BGFX_CONFIG_MAX_PROGRAMS]; Texture m_textures[BGFX_CONFIG_MAX_TEXTURES]; VertexDecl m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS]; - RenderTarget m_renderTargets[BGFX_CONFIG_MAX_RENDER_TARGETS]; + FrameBuffer m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS]; UniformBuffer m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; UniformBuffer m_predefinedUniforms[PredefinedUniform::Count]; UniformRegistry m_uniformReg; @@ -1212,7 +1224,6 @@ namespace bgfx StateCacheT m_samplerStateCache; TextVideoMem m_textVideoMem; - RenderTargetHandle m_rt; TextureStage m_textureStage; @@ -1223,6 +1234,9 @@ namespace bgfx uint32_t m_vsChanges; uint32_t m_fsChanges; + + FrameBufferHandle m_fbh; + bool m_rtMsaa; }; static RendererContext* s_renderCtx; @@ -1398,8 +1412,8 @@ namespace bgfx uint32_t width = s_renderCtx->m_scd.BufferDesc.Width; uint32_t height = s_renderCtx->m_scd.BufferDesc.Height; - RenderTargetHandle rt = BGFX_INVALID_HANDLE; - s_renderCtx->setRenderTarget(rt, false); + FrameBufferHandle fbh = BGFX_INVALID_HANDLE; + s_renderCtx->setFrameBuffer(fbh, false); D3D11_VIEWPORT vp; vp.TopLeftX = 0; @@ -1686,6 +1700,7 @@ namespace bgfx if (imageParse(imageContainer, _mem->data, _mem->size) ) { + m_flags = _flags; m_requestedFormat = (uint8_t)imageContainer.m_format; m_textureFormat = (uint8_t)imageContainer.m_format; @@ -1699,8 +1714,6 @@ namespace bgfx bpp = 32; } - DXGI_FORMAT format = s_textureFormat[m_textureFormat].m_fmt; - if (imageContainer.m_cubeMap) { m_type = TextureCube; @@ -1769,7 +1782,14 @@ namespace bgfx D3D11_SHADER_RESOURCE_VIEW_DESC srvd; memset(&srvd, 0, sizeof(srvd) ); - srvd.Format = format; + srvd.Format = s_textureFormat[m_textureFormat].m_fmtSrv; + + const DXGI_FORMAT format = s_textureFormat[m_textureFormat].m_fmt; + + const bool bufferOnly = 0 != (m_flags&BGFX_TEXTURE_RT_BUFFER_ONLY); + const bool renderTarget = 0 != (m_flags&BGFX_TEXTURE_RT_MASK); + const uint32_t msaaQuality = bx::uint32_satsub( (m_flags&BGFX_TEXTURE_RT_MSAA_MASK)>>BGFX_TEXTURE_RT_MSAA_SHIFT, 1); + const DXGI_SAMPLE_DESC& msaa = s_msaa[msaaQuality]; switch (m_type) { @@ -1780,13 +1800,23 @@ namespace bgfx desc.Width = imageContainer.m_width; desc.Height = imageContainer.m_height; desc.MipLevels = imageContainer.m_numMips; - desc.Format = srvd.Format; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; + desc.Format = format; + desc.SampleDesc = msaa; desc.Usage = kk == 0 ? D3D11_USAGE_DEFAULT : D3D11_USAGE_IMMUTABLE; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.BindFlags = bufferOnly ? 0 : D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; + if (isDepth( (TextureFormat::Enum)m_textureFormat) ) + { + desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL; + desc.Usage = D3D11_USAGE_DEFAULT; + } + else if (renderTarget) + { + desc.BindFlags |= D3D11_BIND_RENDER_TARGET; + desc.Usage = D3D11_USAGE_DEFAULT; + } + if (imageContainer.m_cubeMap) { desc.ArraySize = 6; @@ -1798,7 +1828,7 @@ namespace bgfx { desc.ArraySize = 1; desc.MiscFlags = 0; - srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvd.ViewDimension = 1 < msaa.Count ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D; srvd.Texture2D.MipLevels = imageContainer.m_numMips; } @@ -1813,7 +1843,7 @@ namespace bgfx desc.Height = imageContainer.m_height; desc.Depth = imageContainer.m_depth; desc.MipLevels = imageContainer.m_numMips; - desc.Format = srvd.Format; + desc.Format = format; desc.Usage = kk == 0 ? D3D11_USAGE_DEFAULT : D3D11_USAGE_IMMUTABLE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; @@ -1827,7 +1857,10 @@ namespace bgfx break; } - DX_CHECK(s_renderCtx->m_device->CreateShaderResourceView(m_ptr, &srvd, &m_srv) ); + if (!bufferOnly) + { + DX_CHECK(s_renderCtx->m_device->CreateShaderResourceView(m_ptr, &srvd, &m_srv) ); + } if (convert && 0 != kk) @@ -1851,16 +1884,6 @@ namespace bgfx DX_RELEASE(m_ptr, 0); } - void Texture::commit(uint8_t _stage, uint32_t _flags) - { - TextureStage& ts = s_renderCtx->m_textureStage; - ts.m_srv[_stage] = m_srv; - ts.m_sampler[_stage] = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) - ? s_renderCtx->getSamplerState(_flags) - : m_sampler - ; - } - void Texture::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) { ID3D11DeviceContext* deviceCtx = s_renderCtx->m_deviceCtx; @@ -1898,74 +1921,74 @@ namespace bgfx } } - void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) - { - m_width = _width; - m_height = _height; - m_flags = _flags; - - uint32_t colorFormat = (m_flags&BGFX_RENDER_TARGET_COLOR_MASK)>>BGFX_RENDER_TARGET_COLOR_SHIFT; - uint32_t depthFormat = (m_flags&BGFX_RENDER_TARGET_DEPTH_MASK)>>BGFX_RENDER_TARGET_DEPTH_SHIFT; - - D3D11_TEXTURE2D_DESC desc; - desc.Width = _width; - desc.Height = _height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = s_colorFormat[colorFormat]; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - DX_CHECK(s_renderCtx->m_device->CreateTexture2D(&desc, NULL, &m_colorTexture) ); - DX_CHECK(s_renderCtx->m_device->CreateRenderTargetView(m_colorTexture, NULL, &m_rtv) ); - DX_CHECK(s_renderCtx->m_device->CreateShaderResourceView(m_colorTexture, NULL, &m_srv) ); - - if (0 < depthFormat) - { - D3D11_TEXTURE2D_DESC desc; - desc.Width = _width; - desc.Height = _height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = s_depthFormat[depthFormat]; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - DX_CHECK(s_renderCtx->m_device->CreateTexture2D(&desc, NULL, &m_depthTexture) ); - DX_CHECK(s_renderCtx->m_device->CreateDepthStencilView(m_depthTexture, NULL, &m_dsv) ); -// DX_CHECK(s_renderCtx->m_device->CreateShaderResourceView(m_depthTexture, NULL, &m_srv) ); - } - - m_sampler = s_renderCtx->getSamplerState(_textureFlags); - } - - void RenderTarget::destroy() - { - DX_RELEASE(m_srv, 0); - DX_RELEASE(m_rtv, 0); - DX_RELEASE(m_colorTexture, 0); - DX_RELEASE(m_dsv, 0); - DX_RELEASE(m_depthTexture, 0); - - m_flags = 0; - } - - void RenderTarget::commit(uint8_t _stage, uint32_t _flags) + void Texture::commit(uint8_t _stage, uint32_t _flags) { TextureStage& ts = s_renderCtx->m_textureStage; ts.m_srv[_stage] = m_srv; ts.m_sampler[_stage] = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) - ? s_renderCtx->getSamplerState(_flags) - : m_sampler - ; + ? s_renderCtx->getSamplerState(_flags) + : m_sampler + ; + } + + void Texture::resolve() + { + } + + void FrameBuffer::create(uint8_t _num, const TextureHandle* _handles) + { + for (uint32_t ii = 0; ii < BX_COUNTOF(m_rtv); ++ii) + { + m_rtv[ii] = NULL; + } + m_dsv = NULL; + + m_num = 0; + for (uint32_t ii = 0; ii < _num; ++ii) + { + TextureHandle handle = _handles[ii]; + if (isValid(handle) ) + { + const Texture& texture = s_renderCtx->m_textures[handle.idx]; + if (isDepth( (TextureFormat::Enum)texture.m_textureFormat) ) + { + BX_CHECK(NULL == m_dsv, "Frame buffer already has depth-stencil attached."); + + const uint32_t msaaQuality = bx::uint32_satsub( (texture.m_flags&BGFX_TEXTURE_RT_MSAA_MASK)>>BGFX_TEXTURE_RT_MSAA_SHIFT, 1); + const DXGI_SAMPLE_DESC& msaa = s_msaa[msaaQuality]; + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = s_textureFormat[texture.m_textureFormat].m_fmtDsv; + dsvDesc.ViewDimension = 1 < msaa.Count ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Flags = 0; + dsvDesc.Texture2D.MipSlice = 0; + DX_CHECK(s_renderCtx->m_device->CreateDepthStencilView(texture.m_ptr, &dsvDesc, &m_dsv) ); + } + else + { + DX_CHECK(s_renderCtx->m_device->CreateRenderTargetView(texture.m_ptr, NULL, &m_rtv[m_num]) ); + DX_CHECK(s_renderCtx->m_device->CreateShaderResourceView(texture.m_ptr, NULL, &m_srv[m_num]) ); + m_num++; + } + } + } + } + + void FrameBuffer::destroy() + { + for (uint32_t ii = 0, num = m_num; ii < num; ++ii) + { + DX_RELEASE(m_srv[ii], 0); + DX_RELEASE(m_rtv[ii], 0); + } + + DX_RELEASE(m_dsv, 0); + + m_num = 0; + } + + void FrameBuffer::resolve() + { } void UniformBuffer::create(UniformType::Enum _type, uint16_t _num, bool _alloc) @@ -2134,14 +2157,14 @@ namespace bgfx s_renderCtx->m_textures[_handle.idx].destroy(); } - void Context::rendererCreateRenderTarget(RenderTargetHandle _handle, uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) + void Context::rendererCreateFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const TextureHandle* _textureHandles) { - s_renderCtx->m_renderTargets[_handle.idx].create(_width, _height, _flags, _textureFlags); + s_renderCtx->m_frameBuffers[_handle.idx].create(_num, _textureHandles); } - void Context::rendererDestroyRenderTarget(RenderTargetHandle _handle) + void Context::rendererDestroyFrameBuffer(FrameBufferHandle _handle) { - s_renderCtx->m_renderTargets[_handle.idx].destroy(); + s_renderCtx->m_frameBuffers[_handle.idx].destroy(); } void Context::rendererCreateUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) @@ -2224,7 +2247,7 @@ namespace bgfx uint16_t programIdx = invalidHandle; SortKey key; uint8_t view = 0xff; - RenderTargetHandle rt = BGFX_INVALID_HANDLE; + FrameBufferHandle fbh = BGFX_INVALID_HANDLE; float alphaRef = 0.0f; D3D11_PRIMITIVE_TOPOLOGY primType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; deviceCtx->IASetPrimitiveTopology(primType); @@ -2268,10 +2291,10 @@ namespace bgfx view = key.m_view; programIdx = invalidHandle; - if (m_render->m_rt[view].idx != rt.idx) + if (m_render->m_fb[view].idx != fbh.idx) { - rt = m_render->m_rt[view]; - s_renderCtx->setRenderTarget(rt); + fbh = m_render->m_fb[view]; + s_renderCtx->setFrameBuffer(fbh); } const Rect& rect = m_render->m_rect[view]; @@ -2554,19 +2577,6 @@ namespace bgfx texture.commit(stage, sampler.m_flags); } break; - - case BGFX_SAMPLER_RENDERTARGET_COLOR: - { - RenderTarget& rt = s_renderCtx->m_renderTargets[sampler.m_idx]; - rt.commit(stage, sampler.m_flags); - } - break; - - case BGFX_SAMPLER_RENDERTARGET_DEPTH: - { -// id = s_renderCtx->m_renderTargets[sampler.m_idx].m_depth.m_id; - } - break; } } else @@ -2761,16 +2771,22 @@ namespace bgfx ); pos = 10; - tvm.printf(10, pos++, 0x8e, " Frame: %7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS%s" + tvm.printf(10, pos++, 0x8e, " Frame: %7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS " , double(frameTime)*toMs , double(min)*toMs , double(max)*toMs , freq/frameTime - , !!(m_resolution.m_flags&BGFX_RESET_VSYNC) ? " (vsync)" : "" + ); + + const uint32_t msaa = (m_resolution.m_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + tvm.printf(10, pos++, 0x8e, " Reset flags: [%c] vsync, [%c] MSAAx%d " + , !!(m_resolution.m_flags&BGFX_RESET_VSYNC) ? '\xfe' : ' ' + , 0 != msaa ? '\xfe' : ' ' + , 1<m_num , elapsedCpuMs ); @@ -2781,16 +2797,16 @@ namespace bgfx ); double captureMs = double(captureElapsed)*toMs; - tvm.printf(10, pos++, 0x8e, " Capture: %3.4f [ms]", captureMs); - tvm.printf(10, pos++, 0x8e, " Indices: %7d", statsNumIndices); - tvm.printf(10, pos++, 0x8e, " DVB size: %7d", m_render->m_vboffset); - tvm.printf(10, pos++, 0x8e, " DIB size: %7d", m_render->m_iboffset); + tvm.printf(10, pos++, 0x8e, " Capture: %3.4f [ms]", captureMs); + tvm.printf(10, pos++, 0x8e, " Indices: %7d", statsNumIndices); + tvm.printf(10, pos++, 0x8e, " DVB size: %7d", m_render->m_vboffset); + tvm.printf(10, pos++, 0x8e, " DIB size: %7d", m_render->m_iboffset); uint8_t attr[2] = { 0x89, 0x8a }; uint8_t attrIndex = m_render->m_waitSubmit < m_render->m_waitRender; - tvm.printf(10, pos++, attr[attrIndex&1], "Submit wait: %3.4f [ms]", m_render->m_waitSubmit*toMs); - tvm.printf(10, pos++, attr[(attrIndex+1)&1], "Render wait: %3.4f [ms]", m_render->m_waitRender*toMs); + tvm.printf(10, pos++, attr[attrIndex&1], " Submit wait: %3.4f [ms]", m_render->m_waitSubmit*toMs); + tvm.printf(10, pos++, attr[(attrIndex+1)&1], " Render wait: %3.4f [ms]", m_render->m_waitRender*toMs); min = frameTime; max = frameTime; diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index b15470e05..aa9a2d536 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -260,6 +260,7 @@ namespace bgfx void destroy(); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS); + void resolve(); union { @@ -270,41 +271,28 @@ namespace bgfx ID3D11ShaderResourceView* m_srv; ID3D11SamplerState* m_sampler; + uint32_t m_flags; uint8_t m_type; uint8_t m_requestedFormat; uint8_t m_textureFormat; uint8_t m_numMips; }; - struct RenderTarget + struct FrameBuffer { - RenderTarget() - : m_colorTexture(NULL) - , m_depthTexture(NULL) - , m_rtv(NULL) - , m_dsv(NULL) - , m_srv(NULL) - , m_width(0) - , m_height(0) - , m_flags(0) - , m_depthOnly(false) + FrameBuffer() + : m_num(0) { } - void create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags); + void create(uint8_t _num, const TextureHandle* _handles); void destroy(); - void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS); + void resolve(); - ID3D11Texture2D* m_colorTexture; - ID3D11Texture2D* m_depthTexture; - ID3D11RenderTargetView* m_rtv; + ID3D11RenderTargetView* m_rtv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; + ID3D11ShaderResourceView* m_srv[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; ID3D11DepthStencilView* m_dsv; - ID3D11ShaderResourceView* m_srv; - ID3D11SamplerState* m_sampler; - uint16_t m_width; - uint16_t m_height; - uint32_t m_flags; - bool m_depthOnly; + uint8_t m_num; }; } // namespace bgfx diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 5d1ba4fa7..ce4397155 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -233,7 +233,7 @@ namespace bgfx #if defined(D3D_DISABLE_9EX) { D3DFMT_UNKNOWN }, // D0S8 #else - { D3DFMT_S8_LOCKABLE }, // D0S8 + { D3DFMT_INTZ /*D3DFMT_S8_LOCKABLE*/ }, // D0S8 #endif // defined(D3D_DISABLE_9EX) }; @@ -278,7 +278,7 @@ namespace bgfx , m_instancing(false) , m_rtMsaa(false) { - m_rt.idx = invalidHandle; + m_fbh.idx = invalidHandle; } void init() @@ -433,18 +433,21 @@ namespace bgfx BX_TRACE("Max vertex shader constants: %d", m_caps.MaxVertexShaderConst); BX_TRACE("Max fragment shader 2.0 instr. slots: %d", m_caps.PS20Caps.NumInstructionSlots); BX_TRACE("Max fragment shader 3.0 instr. slots: %d", m_caps.MaxPixelShader30InstructionSlots); + BX_TRACE("Num simultaneous render targets: %d", m_caps.NumSimultaneousRTs); g_caps.supported |= ( 0 | BGFX_CAPS_TEXTURE_FORMAT_BC1 | BGFX_CAPS_TEXTURE_FORMAT_BC2 | BGFX_CAPS_TEXTURE_FORMAT_BC3 | BGFX_CAPS_TEXTURE_3D - | BGFX_CAPS_TEXTURE_DEPTH_MASK | BGFX_CAPS_VERTEX_ATTRIB_HALF | BGFX_CAPS_FRAGMENT_DEPTH ); g_caps.maxTextureSize = bx::uint32_min(m_caps.MaxTextureWidth, m_caps.MaxTextureHeight); + m_caps.NumSimultaneousRTs = bx::uint32_min(m_caps.NumSimultaneousRTs, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS); + g_caps.maxFBAttachments = (uint8_t)m_caps.NumSimultaneousRTs; + #if BGFX_CONFIG_RENDERER_USE_EXTENSIONS BX_TRACE("Extended formats:"); for (uint32_t ii = 0; ii < ExtendedFormat::Count; ++ii) @@ -474,6 +477,8 @@ namespace bgfx g_caps.supported |= 0 | (D3DFMT_UNKNOWN != s_textureFormat[TextureFormat::BC4].m_fmt ? BGFX_CAPS_TEXTURE_FORMAT_BC4 : 0) | (D3DFMT_UNKNOWN != s_textureFormat[TextureFormat::BC5].m_fmt ? BGFX_CAPS_TEXTURE_FORMAT_BC5 : 0) + | (s_extendedFormats[ExtendedFormat::Df16].m_supported ? BGFX_CAPS_TEXTURE_FORMAT_D16F : 0) + | (s_extendedFormats[ExtendedFormat::Df24].m_supported ? BGFX_CAPS_TEXTURE_FORMAT_D24F : 0) ; g_caps.supported |= m_instancing ? BGFX_CAPS_INSTANCING : 0; #endif // BGFX_CONFIG_RENDERER_USE_EXTENSIONS @@ -565,11 +570,6 @@ namespace bgfx m_vertexDecls[ii].destroy(); } - for (uint32_t ii = 0; ii < BX_COUNTOF(m_renderTargets); ++ii) - { - m_renderTargets[ii].destroy(); - } - #if BGFX_CONFIG_RENDERER_DIRECT3D9EX if (NULL != m_d3d9ex) { @@ -658,41 +658,43 @@ namespace bgfx } } - void setRenderTarget(RenderTargetHandle _rt, bool _msaa = true) + void setFrameBuffer(FrameBufferHandle _fbh, bool _msaa = true) { - if (!isValid(_rt) ) + if (!isValid(_fbh) ) { DX_CHECK(m_device->SetRenderTarget(0, m_backBufferColor) ); + for (uint32_t ii = 1, num = g_caps.maxFBAttachments; ii < num; ++ii) + { + DX_CHECK(m_device->SetRenderTarget(ii, NULL) ); + } DX_CHECK(m_device->SetDepthStencilSurface(m_backBufferDepthStencil) ); } else { - RenderTarget& renderTarget = m_renderTargets[_rt.idx]; - if (NULL != renderTarget.m_rt) + const FrameBuffer& frameBuffer = m_frameBuffers[_fbh.idx]; + for (uint32_t ii = 0, num = frameBuffer.m_num; ii < num; ++ii) { - DX_CHECK(m_device->SetRenderTarget(0, renderTarget.m_rt) ); - } - else - { - DX_CHECK(m_device->SetRenderTarget(0, renderTarget.m_color) ); + DX_CHECK(m_device->SetRenderTarget(ii, frameBuffer.m_color[ii]) ); } - DX_CHECK(m_device->SetDepthStencilSurface(NULL != renderTarget.m_depth ? renderTarget.m_depth : m_backBufferDepthStencil) ); + for (uint32_t ii = frameBuffer.m_num, num = g_caps.maxFBAttachments; ii < num; ++ii) + { + DX_CHECK(m_device->SetRenderTarget(ii, NULL) ); + } + + IDirect3DSurface9* depthStencil = frameBuffer.m_depthStencil; + DX_CHECK(m_device->SetDepthStencilSurface(NULL != depthStencil ? depthStencil : m_backBufferDepthStencil) ); } - if (isValid(m_rt) - && m_rt.idx != _rt.idx + if (isValid(m_fbh) + && m_fbh.idx != _fbh.idx && m_rtMsaa) { - RenderTarget& renderTarget = m_renderTargets[m_rt.idx]; - if (!renderTarget.m_depthOnly - && renderTarget.m_rt != NULL) - { - renderTarget.resolve(); - } + FrameBuffer& frameBuffer = m_frameBuffers[m_fbh.idx]; + frameBuffer.resolve(); } - m_rt = _rt; + m_fbh = _fbh; m_rtMsaa = _msaa; } @@ -781,6 +783,10 @@ namespace bgfx } DX_CHECK(m_device->SetRenderTarget(0, m_backBufferColor) ); + for (uint32_t ii = 1, num = g_caps.maxFBAttachments; ii < num; ++ii) + { + DX_CHECK(m_device->SetRenderTarget(ii, NULL) ); + } DX_CHECK(m_device->SetDepthStencilSurface(m_backBufferDepthStencil) ); DX_CHECK(m_device->SetVertexShader(NULL) ); DX_CHECK(m_device->SetPixelShader(NULL) ); @@ -802,9 +808,14 @@ namespace bgfx m_vertexBuffers[ii].preReset(); } - for (uint32_t ii = 0; ii < BX_COUNTOF(m_renderTargets); ++ii) + for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) { - m_renderTargets[ii].preReset(); + m_frameBuffers[ii].preReset(); + } + + for (uint32_t ii = 0; ii < BX_COUNTOF(m_textures); ++ii) + { + m_textures[ii].preReset(); } } @@ -825,9 +836,14 @@ namespace bgfx m_vertexBuffers[ii].postReset(); } - for (uint32_t ii = 0; ii < BX_COUNTOF(m_renderTargets); ++ii) + for (uint32_t ii = 0; ii < BX_COUNTOF(m_textures); ++ii) { - m_renderTargets[ii].postReset(); + m_textures[ii].postReset(); + } + + for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii) + { + m_frameBuffers[ii].postReset(); } } @@ -1042,7 +1058,7 @@ namespace bgfx Program m_program[BGFX_CONFIG_MAX_PROGRAMS]; Texture m_textures[BGFX_CONFIG_MAX_TEXTURES]; VertexDeclaration m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS]; - RenderTarget m_renderTargets[BGFX_CONFIG_MAX_RENDER_TARGETS]; + FrameBuffer m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS]; UniformRegistry m_uniformReg; void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; @@ -1055,7 +1071,8 @@ namespace bgfx uint8_t m_updateTextureMip; TextVideoMem m_textVideoMem; - RenderTargetHandle m_rt; + + FrameBufferHandle m_fbh; bool m_rtMsaa; }; @@ -1363,69 +1380,138 @@ namespace bgfx } } - void Texture::createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips, D3DFORMAT _fmt) + void Texture::createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips) { + m_width = (uint16_t)_width; + m_height = (uint16_t)_height; + m_numMips = _numMips; m_type = Texture2D; + const TextureFormat::Enum fmt = (TextureFormat::Enum)m_textureFormat; + + DWORD usage = 0; + D3DPOOL pool = s_renderCtx->m_pool; + + const bool renderTarget = 0 != (m_flags&BGFX_TEXTURE_RT_MASK); + if (isDepth(fmt) ) + { + usage = D3DUSAGE_DEPTHSTENCIL; + pool = D3DPOOL_DEFAULT; + } + else if (renderTarget) + { + usage = D3DUSAGE_RENDERTARGET; + pool = D3DPOOL_DEFAULT; + } + + if (renderTarget) + { + uint32_t msaaQuality = ( (m_flags&BGFX_TEXTURE_RT_MSAA_MASK)>>BGFX_TEXTURE_RT_MSAA_SHIFT); + msaaQuality = bx::uint32_satsub(msaaQuality, 1); + + bool bufferOnly = 0 != (m_flags&BGFX_TEXTURE_RT_BUFFER_ONLY); + + if (0 != msaaQuality + || bufferOnly) + { + const Msaa& msaa = s_msaa[msaaQuality]; + + if (isDepth(fmt) ) + { + DX_CHECK(s_renderCtx->m_device->CreateDepthStencilSurface( + m_width + , m_height + , s_textureFormat[m_textureFormat].m_fmt + , msaa.m_type + , msaa.m_quality + , FALSE + , &m_surface + , NULL + ) ); + } + else + { + DX_CHECK(s_renderCtx->m_device->CreateRenderTarget( + m_width + , m_height + , s_textureFormat[m_textureFormat].m_fmt + , msaa.m_type + , msaa.m_quality + , FALSE + , &m_surface + , NULL + ) ); + } + + if (bufferOnly) + { + // This is render buffer, there is no sampling, no need + // to create texture. + return; + } + } + } DX_CHECK(s_renderCtx->m_device->CreateTexture(_width , _height , _numMips - , 0 - , _fmt - , s_renderCtx->m_pool + , usage + , s_textureFormat[fmt].m_fmt + , pool , &m_texture2d , NULL ) ); - BGFX_FATAL(NULL != m_texture2d, Fatal::UnableToCreateTexture, "Failed to create texture (size: %dx%d, mips: %d, fmt: 0x%08x)." + BGFX_FATAL(NULL != m_texture2d, Fatal::UnableToCreateTexture, "Failed to create texture (size: %dx%d, mips: %d, fmt: %d)." , _width , _height , _numMips - , _fmt + , getName(fmt) ); } - void Texture::createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _numMips, D3DFORMAT _fmt) + void Texture::createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _numMips) { m_type = Texture3D; + const TextureFormat::Enum fmt = (TextureFormat::Enum)m_textureFormat; DX_CHECK(s_renderCtx->m_device->CreateVolumeTexture(_width , _height , _depth , _numMips , 0 - , _fmt + , s_textureFormat[fmt].m_fmt , s_renderCtx->m_pool , &m_texture3d , NULL ) ); - BGFX_FATAL(NULL != m_texture3d, Fatal::UnableToCreateTexture, "Failed to create volume texture (size: %dx%dx%d, mips: %d, fmt: 0x%08x)." + BGFX_FATAL(NULL != m_texture3d, Fatal::UnableToCreateTexture, "Failed to create volume texture (size: %dx%dx%d, mips: %d, fmt: %s)." , _width , _height , _depth , _numMips - , _fmt + , getName(fmt) ); } - void Texture::createCubeTexture(uint32_t _edge, uint32_t _numMips, D3DFORMAT _fmt) + void Texture::createCubeTexture(uint32_t _edge, uint32_t _numMips) { m_type = TextureCube; + const TextureFormat::Enum fmt = (TextureFormat::Enum)m_textureFormat; DX_CHECK(s_renderCtx->m_device->CreateCubeTexture(_edge , _numMips , 0 - , _fmt + , s_textureFormat[fmt].m_fmt , s_renderCtx->m_pool , &m_textureCube , NULL ) ); - BGFX_FATAL(NULL != m_textureCube, Fatal::UnableToCreateTexture, "Failed to create cube texture (edge: %d, mips: %d, fmt: 0x%08x)." + BGFX_FATAL(NULL != m_textureCube, Fatal::UnableToCreateTexture, "Failed to create cube texture (edge: %d, mips: %d, fmt: %s)." , _edge , _numMips - , _fmt + , getName(fmt) ); } @@ -1585,19 +1671,22 @@ namespace bgfx bpp = 32; } - D3DFORMAT format = s_textureFormat[m_textureFormat].m_fmt; - if (imageContainer.m_cubeMap) { - createCubeTexture(imageContainer.m_width, imageContainer.m_numMips, format); + createCubeTexture(imageContainer.m_width, imageContainer.m_numMips); } else if (imageContainer.m_depth > 1) { - createVolumeTexture(imageContainer.m_width, imageContainer.m_height, imageContainer.m_depth, imageContainer.m_numMips, format); + createVolumeTexture(imageContainer.m_width, imageContainer.m_height, imageContainer.m_depth, imageContainer.m_numMips); } else { - createTexture(imageContainer.m_width, imageContainer.m_height, imageContainer.m_numMips, format); + createTexture(imageContainer.m_width, imageContainer.m_height, imageContainer.m_numMips); + } + + if (0 != (_flags&BGFX_TEXTURE_RT_BUFFER_ONLY) ) + { + return; } // For BC4 and B5 in DX9 LockRect returns wrong number of @@ -1740,161 +1829,180 @@ namespace bgfx DX_CHECK(s_renderCtx->m_device->SetTexture(_stage, m_ptr) ); } - void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) + void Texture::resolve() const { - m_width = _width; - m_height = _height; - m_flags = _flags; - m_textureFlags = (_textureFlags&(BGFX_TEXTURE_MIN_MASK|BGFX_TEXTURE_MAG_MASK) ) - | BGFX_TEXTURE_U_CLAMP - | BGFX_TEXTURE_V_CLAMP - ; - - createTextures(); - } - - void RenderTarget::createTextures() - { - if (0 != m_flags) + if (NULL != m_surface + && NULL != m_texture2d) { - m_msaa = s_msaa[(m_flags&BGFX_RENDER_TARGET_MSAA_MASK)>>BGFX_RENDER_TARGET_MSAA_SHIFT]; - const uint32_t colorFormat = (m_flags&BGFX_RENDER_TARGET_COLOR_MASK)>>BGFX_RENDER_TARGET_COLOR_SHIFT; - const uint32_t depthFormat = (m_flags&BGFX_RENDER_TARGET_DEPTH_MASK)>>BGFX_RENDER_TARGET_DEPTH_SHIFT; - m_depthOnly = (0 == colorFormat && 0 < depthFormat); - - // CheckDeviceFormat D3DUSAGE_SRGBWRITE - - if (m_depthOnly) - { - DX_CHECK(s_renderCtx->m_device->CreateRenderTarget(1 - , 1 - , D3DFMT_R5G6B5 - , D3DMULTISAMPLE_NONE - , 0 - , false - , &m_rt - , NULL - ) ); - - BGFX_FATAL(m_rt, Fatal::UnableToCreateRenderTarget, "Unable to create 1x1 render target."); - - DX_CHECK(s_renderCtx->m_device->CreateTexture(m_width - , m_height - , 1 - , D3DUSAGE_DEPTHSTENCIL - , s_depthFormat[depthFormat] - , D3DPOOL_DEFAULT - , &m_depthTexture - , NULL - ) ); - - BGFX_FATAL(m_depthTexture, Fatal::UnableToCreateRenderTarget, "Unable to create depth texture."); - - DX_CHECK(m_depthTexture->GetSurfaceLevel(0, &m_depth) ); - } - else - { - if (D3DMULTISAMPLE_NONE != m_msaa.m_type) - { - DX_CHECK(s_renderCtx->m_device->CreateRenderTarget(m_width - , m_height - , s_colorFormat[colorFormat] - , m_msaa.m_type - , m_msaa.m_quality - , false - , &m_rt - , NULL - ) ); - - BGFX_FATAL(m_rt, Fatal::UnableToCreateRenderTarget, "Unable to create MSAA render target."); - } - - if (0 < colorFormat) - { - DX_CHECK(s_renderCtx->m_device->CreateTexture(m_width - , m_height - , 1 - , D3DUSAGE_RENDERTARGET - , s_colorFormat[colorFormat] - , D3DPOOL_DEFAULT - , &m_colorTexture - , NULL - ) ); - - BGFX_FATAL(m_colorTexture, Fatal::UnableToCreateRenderTarget, "Unable to create color render target."); - - DX_CHECK(m_colorTexture->GetSurfaceLevel(0, &m_color) ); - } - - if (0 < depthFormat) - { - DX_CHECK(s_renderCtx->m_device->CreateDepthStencilSurface(m_width - , m_height - , s_depthFormat[depthFormat] - , m_msaa.m_type - , m_msaa.m_quality - , FALSE - , &m_depth - , NULL - ) ); - - BGFX_FATAL(m_depth, Fatal::UnableToCreateRenderTarget, "Unable to create depth stencil surface."); - } - } - } - } - - void RenderTarget::destroyTextures() - { - if (0 != m_flags) - { - if (m_depthOnly) - { - DX_RELEASE(m_rt, 0); - - DX_RELEASE(m_depth, 1); - DX_RELEASE(m_depthTexture, 0); - } - else - { - uint32_t colorFormat = (m_flags&BGFX_RENDER_TARGET_COLOR_MASK)>>BGFX_RENDER_TARGET_COLOR_SHIFT; - uint32_t depthFormat = (m_flags&BGFX_RENDER_TARGET_DEPTH_MASK)>>BGFX_RENDER_TARGET_DEPTH_SHIFT; - - if (D3DMULTISAMPLE_NONE != m_msaa.m_type) - { - DX_RELEASE(m_rt, 0); - } - - if (0 < colorFormat) - { - DX_RELEASE(m_color, 1); - DX_RELEASE(m_colorTexture, 0); - } - - if (0 < depthFormat) - { - DX_RELEASE(m_depth, 0); - } - } - } - } - - void RenderTarget::commit(uint8_t _stage, uint32_t _textureFlags) - { - s_renderCtx->setSamplerState(_stage, 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _textureFlags) ? _textureFlags : m_textureFlags); - DX_CHECK(s_renderCtx->m_device->SetTexture(_stage, m_depthOnly ? m_depthTexture : m_colorTexture) ); - } - - void RenderTarget::resolve() - { -#if BX_PLATFORM_WINDOWS - DX_CHECK(s_renderCtx->m_device->StretchRect(m_rt + IDirect3DSurface9* surface; + DX_CHECK(m_texture2d->GetSurfaceLevel(0, &surface) ); + DX_CHECK(s_renderCtx->m_device->StretchRect(m_surface , NULL - , m_color + , surface , NULL - , D3DTEXF_NONE + , D3DTEXF_LINEAR ) ); -#endif // BX_PLATFORM_WINDOWS + DX_RELEASE(surface, 1); + } + } + + void Texture::preReset() + { + TextureFormat::Enum fmt = (TextureFormat::Enum)m_textureFormat; + if (TextureFormat::Unknown != fmt + && (isDepth(fmt) || !!(m_flags&BGFX_TEXTURE_RT_MASK) ) ) + { + DX_RELEASE(m_ptr, 0); + DX_RELEASE(m_surface, 0); + } + } + + void Texture::postReset() + { + TextureFormat::Enum fmt = (TextureFormat::Enum)m_textureFormat; + if (TextureFormat::Unknown != fmt + && (isDepth(fmt) || !!(m_flags&BGFX_TEXTURE_RT_MASK) ) ) + { + createTexture(m_width, m_height, m_numMips); + } + } + + void FrameBuffer::create(uint8_t _num, const TextureHandle* _handles) + { + for (uint32_t ii = 0; ii < BX_COUNTOF(m_color); ++ii) + { + m_color[ii] = NULL; + } + m_depthStencil = NULL; + + m_num = 0; + m_needResolve = false; + for (uint32_t ii = 0; ii < _num; ++ii) + { + TextureHandle handle = _handles[ii]; + if (isValid(handle) ) + { + const Texture& texture = s_renderCtx->m_textures[handle.idx]; + + if (isDepth( (TextureFormat::Enum)texture.m_textureFormat) ) + { + m_depthHandle = handle; + if (NULL != texture.m_surface) + { + m_depthStencil = texture.m_surface; + m_depthStencil->AddRef(); + } + else + { + DX_CHECK(texture.m_texture2d->GetSurfaceLevel(0, &m_depthStencil) ); + } + } + else + { + m_colorHandle[m_num] = handle; + if (NULL != texture.m_surface) + { + m_color[m_num] = texture.m_surface; + m_color[m_num]->AddRef(); + } + else + { + DX_CHECK(texture.m_texture2d->GetSurfaceLevel(0, &m_color[m_num]) ); + } + m_num++; + } + + m_needResolve |= (NULL != texture.m_surface) && (NULL != texture.m_texture2d); + } + } + } + + void FrameBuffer::destroy() + { + for (uint32_t ii = 0, num = m_num; ii < num; ++ii) + { + m_colorHandle[ii].idx = invalidHandle; + + IDirect3DSurface9* ptr = m_color[ii]; + if (NULL != ptr) + { + ptr->Release(); + m_color[ii] = NULL; + } + } + + if (NULL != m_depthStencil) + { + m_depthStencil->Release(); + m_depthStencil = NULL; + } + + m_num = 0; + m_depthHandle.idx = invalidHandle; + } + + void FrameBuffer::resolve() const + { + if (m_needResolve) + { + if (isValid(m_depthHandle) ) + { + const Texture& texture = s_renderCtx->m_textures[m_depthHandle.idx]; + texture.resolve(); + } + + for (uint32_t ii = 0, num = m_num; ii < num; ++ii) + { + const Texture& texture = s_renderCtx->m_textures[m_colorHandle[ii].idx]; + texture.resolve(); + } + } + } + + void FrameBuffer::preReset() + { + for (uint32_t ii = 0, num = m_num; ii < num; ++ii) + { + m_color[ii]->Release(); + m_color[ii] = NULL; + } + + if (isValid(m_depthHandle) ) + { + m_depthStencil->Release(); + m_depthStencil = NULL; + } + } + + void FrameBuffer::postReset() + { + for (uint32_t ii = 0, num = m_num; ii < num; ++ii) + { + Texture& texture = s_renderCtx->m_textures[m_colorHandle[ii].idx]; + if (NULL != texture.m_surface) + { + m_color[ii] = texture.m_surface; + m_color[ii]->AddRef(); + } + else + { + DX_CHECK(texture.m_texture2d->GetSurfaceLevel(0, &m_color[ii]) ); + } + } + + if (isValid(m_depthHandle) ) + { + Texture& texture = s_renderCtx->m_textures[m_depthHandle.idx]; + if (NULL != texture.m_surface) + { + m_depthStencil = texture.m_surface; + m_depthStencil->AddRef(); + } + else + { + DX_CHECK(texture.m_texture2d->GetSurfaceLevel(0, &m_depthStencil) ); + } + } } void ConstantBuffer::commit() @@ -1971,8 +2079,8 @@ namespace bgfx uint32_t width = s_renderCtx->m_params.BackBufferWidth; uint32_t height = s_renderCtx->m_params.BackBufferHeight; - RenderTargetHandle rt = BGFX_INVALID_HANDLE; - s_renderCtx->setRenderTarget(rt, false); + FrameBufferHandle fbh = BGFX_INVALID_HANDLE; + s_renderCtx->setFrameBuffer(fbh, false); D3DVIEWPORT9 vp; vp.X = 0; @@ -2168,14 +2276,14 @@ namespace bgfx s_renderCtx->m_textures[_handle.idx].destroy(); } - void Context::rendererCreateRenderTarget(RenderTargetHandle _handle, uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) + void Context::rendererCreateFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const TextureHandle* _textureHandles) { - s_renderCtx->m_renderTargets[_handle.idx].create(_width, _height, _flags, _textureFlags); + s_renderCtx->m_frameBuffers[_handle.idx].create(_num, _textureHandles); } - void Context::rendererDestroyRenderTarget(RenderTargetHandle _handle) + void Context::rendererDestroyFrameBuffer(FrameBufferHandle _handle) { - s_renderCtx->m_renderTargets[_handle.idx].destroy(); + s_renderCtx->m_frameBuffers[_handle.idx].destroy(); } void Context::rendererCreateUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) @@ -2260,7 +2368,7 @@ namespace bgfx uint16_t programIdx = invalidHandle; SortKey key; uint8_t view = 0xff; - RenderTargetHandle rt = BGFX_INVALID_HANDLE; + FrameBufferHandle fbh = BGFX_INVALID_HANDLE; float alphaRef = 0.0f; uint32_t blendFactor = 0; D3DPRIMITIVETYPE primType = D3DPT_TRIANGLELIST; @@ -2306,10 +2414,10 @@ namespace bgfx view = key.m_view; programIdx = invalidHandle; - if (m_render->m_rt[view].idx != rt.idx) + if (m_render->m_fb[view].idx != fbh.idx) { - rt = m_render->m_rt[view]; - s_renderCtx->setRenderTarget(rt); + fbh = m_render->m_fb[view]; + s_renderCtx->setFrameBuffer(fbh); } const Rect& rect = m_render->m_rect[view]; @@ -2708,14 +2816,6 @@ namespace bgfx case BGFX_SAMPLER_TEXTURE: s_renderCtx->m_textures[sampler.m_idx].commit(stage, sampler.m_flags); break; - - case BGFX_SAMPLER_RENDERTARGET_COLOR: - s_renderCtx->m_renderTargets[sampler.m_idx].commit(stage, sampler.m_flags); - break; - - case BGFX_SAMPLER_RENDERTARGET_DEPTH: -// id = s_renderCtx->m_renderTargets[sampler.m_idx].m_depth.m_id; - break; } } else @@ -2904,36 +3004,42 @@ namespace bgfx tvm.printf(0, pos++, 0x0f, " Device: %s (%s)", identifier.Description, identifier.Driver); pos = 10; - tvm.printf(10, pos++, 0x8e, " Frame: %7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS%s" + tvm.printf(10, pos++, 0x8e, " Frame: %7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS " , double(frameTime)*toMs , double(min)*toMs , double(max)*toMs , freq/frameTime - , !!(m_resolution.m_flags&BGFX_RESET_VSYNC) ? " (vsync)" : "" + ); + + const uint32_t msaa = (m_resolution.m_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + tvm.printf(10, pos++, 0x8e, " Reset flags: [%c] vsync, [%c] MSAAx%d " + , !!(m_resolution.m_flags&BGFX_RESET_VSYNC) ? '\xfe' : ' ' + , 0 != msaa ? '\xfe' : ' ' + , 1<m_num , elapsedCpuMs ); - tvm.printf(10, pos++, 0x8e, " Prims: %7d (#inst: %5d), submitted: %7d" + tvm.printf(10, pos++, 0x8e, " Prims: %7d (#inst: %5d), submitted: %7d" , statsNumPrimsRendered , statsNumInstances , statsNumPrimsSubmitted ); double captureMs = double(captureElapsed)*toMs; - tvm.printf(10, pos++, 0x8e, " Capture: %3.4f [ms]", captureMs); - tvm.printf(10, pos++, 0x8e, " Indices: %7d", statsNumIndices); - tvm.printf(10, pos++, 0x8e, " DVB size: %7d", m_render->m_vboffset); - tvm.printf(10, pos++, 0x8e, " DIB size: %7d", m_render->m_iboffset); + tvm.printf(10, pos++, 0x8e, " Capture: %3.4f [ms]", captureMs); + tvm.printf(10, pos++, 0x8e, " Indices: %7d", statsNumIndices); + tvm.printf(10, pos++, 0x8e, " DVB size: %7d", m_render->m_vboffset); + tvm.printf(10, pos++, 0x8e, " DIB size: %7d", m_render->m_iboffset); uint8_t attr[2] = { 0x89, 0x8a }; uint8_t attrIndex = m_render->m_waitSubmit < m_render->m_waitRender; - tvm.printf(10, pos++, attr[attrIndex&1], "Submit wait: %3.4f [ms]", m_render->m_waitSubmit*toMs); - tvm.printf(10, pos++, attr[(attrIndex+1)&1], "Render wait: %3.4f [ms]", m_render->m_waitRender*toMs); + tvm.printf(10, pos++, attr[attrIndex&1], " Submit wait: %3.4f [ms]", m_render->m_waitSubmit*toMs); + tvm.printf(10, pos++, attr[(attrIndex+1)&1], " Render wait: %3.4f [ms]", m_render->m_waitRender*toMs); min = frameTime; max = frameTime; diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index 9227f926f..05469fa56 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -298,12 +298,14 @@ namespace bgfx Texture() : m_ptr(NULL) + , m_surface(NULL) + , m_textureFormat(TextureFormat::Unknown) { } - void createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips, D3DFORMAT _fmt); - void createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _numMips, D3DFORMAT _fmt); - void createCubeTexture(uint32_t _edge, uint32_t _numMips, D3DFORMAT _fmt); + void createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips); + void createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _numMips); + void createCubeTexture(uint32_t _edge, uint32_t _numMips); uint8_t* lock(uint8_t _side, uint8_t _lod, uint32_t& _pitch, uint32_t& _slicePitch, const Rect* _rect = NULL); void unlock(uint8_t _side, uint8_t _lod); @@ -314,12 +316,18 @@ namespace bgfx void destroy() { DX_RELEASE(m_ptr, 0); + DX_RELEASE(m_surface, 0); + m_textureFormat = TextureFormat::Unknown; } void updateBegin(uint8_t _side, uint8_t _mip); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void updateEnd(); void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS); + void resolve() const; + + void preReset(); + void postReset(); union { @@ -329,61 +337,37 @@ namespace bgfx IDirect3DCubeTexture9* m_textureCube; }; + IDirect3DSurface9* m_surface; uint32_t m_flags; + uint16_t m_width; + uint16_t m_height; + uint8_t m_numMips; uint8_t m_type; uint8_t m_requestedFormat; uint8_t m_textureFormat; }; - struct RenderTarget + struct FrameBuffer { - RenderTarget() - : m_rt(NULL) - , m_colorTexture(NULL) - , m_color(NULL) - , m_depthTexture(NULL) - , m_depth(NULL) - , m_width(0) - , m_height(0) - , m_flags(0) - , m_depthOnly(false) + FrameBuffer() + : m_num(0) + , m_needResolve(0) { + m_depthHandle.idx = invalidHandle; } - void create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags); - void createTextures(); - void destroyTextures(); + void create(uint8_t _num, const TextureHandle* _handles); + void destroy(); + void resolve() const; + void preReset(); + void postReset(); - void destroy() - { - destroyTextures(); - m_flags = 0; - } - - void preReset() - { - destroyTextures(); - } - - void postReset() - { - createTextures(); - } - - void commit(uint8_t _stage, uint32_t _textureFlags = BGFX_SAMPLER_DEFAULT_FLAGS); - void resolve(); - - Msaa m_msaa; - IDirect3DSurface9* m_rt; - IDirect3DTexture9* m_colorTexture; - IDirect3DSurface9* m_color; - IDirect3DTexture9* m_depthTexture; - IDirect3DSurface9* m_depth; - uint16_t m_width; - uint16_t m_height; - uint32_t m_flags; - uint32_t m_textureFlags; - bool m_depthOnly; + IDirect3DSurface9* m_color[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; + IDirect3DSurface9* m_depthStencil; + TextureHandle m_colorHandle[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS-1]; + TextureHandle m_depthHandle; + uint8_t m_num; + bool m_needResolve; }; } // namespace bgfx diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 42eee57c2..7603d30f3 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -136,46 +136,6 @@ namespace bgfx GL_BACK, }; - struct RenderTargetColorFormat - { - GLenum m_internalFmt; - GLenum m_type; - uint8_t m_bpp; - }; - - // Specifies the internal format of the texture. - // Must be one of the following symbolic constants: - // GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA. - static const RenderTargetColorFormat s_colorFormat[] = - { - { 0, 0, 0 }, // ignored - { GL_RGBA8, GL_UNSIGNED_BYTE, 32 }, - { GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, 32 }, - { GL_RGBA16, GL_UNSIGNED_SHORT, 64 }, - { GL_RGBA16F, GL_HALF_FLOAT, 64 }, - { GL_R16F, GL_HALF_FLOAT, 16 }, - { GL_R32F, GL_FLOAT, 32 }, - }; - - struct RenderTargetDepthFormat - { - GLenum m_internalFmt; - GLenum m_attachment; - }; - - static const RenderTargetDepthFormat s_depthFormat[] = - { - { 0, 0 }, // ignored - { GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT }, // D16 - { GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT }, // D24 - { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT }, // D24S8 - { GL_DEPTH_COMPONENT32, GL_DEPTH_ATTACHMENT }, // D32 - { GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT }, // D16F - { GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT }, // D24F - { GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT }, // D32F - { GL_STENCIL_INDEX8, GL_STENCIL_ATTACHMENT }, // D0S8 - }; - static const GLenum s_textureAddress[] = { GL_REPEAT, @@ -580,7 +540,7 @@ namespace bgfx , m_backBufferFbo(0) , m_msaaBackBufferFbo(0) { - m_rt.idx = invalidHandle; + m_fbh.idx = invalidHandle; memset(&m_resolution, 0, sizeof(m_resolution) ); } @@ -603,31 +563,28 @@ namespace bgfx } } - uint32_t setRenderTarget(RenderTargetHandle _rt, uint32_t _height, bool _msaa = true) + uint32_t setFrameBuffer(FrameBufferHandle _fbh, uint32_t _height, bool _msaa = true) { - if (isValid(m_rt) - && m_rt.idx != _rt.idx + if (isValid(m_fbh) + && m_fbh.idx != _fbh.idx && m_rtMsaa) { - RenderTarget& renderTarget = m_renderTargets[m_rt.idx]; - if (0 != renderTarget.m_fbo[1]) - { - renderTarget.resolve(); - } + FrameBuffer& frameBuffer = m_frameBuffers[m_fbh.idx]; + frameBuffer.resolve(); } - if (!isValid(_rt) ) + if (!isValid(_fbh) ) { GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) ); } else { - RenderTarget& renderTarget = m_renderTargets[_rt.idx]; - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.m_fbo[0]) ); - _height = renderTarget.m_height; + FrameBuffer& frameBuffer = m_frameBuffers[_fbh.idx]; + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer.m_fbo[0]) ); + _height = frameBuffer.m_height; } - m_rt = _rt; + m_fbh = _fbh; m_rtMsaa = _msaa; return _height; @@ -910,7 +867,7 @@ namespace bgfx Program m_program[BGFX_CONFIG_MAX_PROGRAMS]; Texture m_textures[BGFX_CONFIG_MAX_TEXTURES]; VertexDecl m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS]; - RenderTarget m_renderTargets[BGFX_CONFIG_MAX_RENDER_TARGETS]; + FrameBuffer m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS]; UniformRegistry m_uniformReg; void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; #if BGFX_CONFIG_RENDERER_OPENGL @@ -923,9 +880,10 @@ namespace bgfx #endif // !BGFX_CONFIG_RENDERER_OPENGLES2 TextVideoMem m_textVideoMem; - RenderTargetHandle m_rt; bool m_rtMsaa; + FrameBufferHandle m_fbh; + Resolution m_resolution; void* m_capture; uint32_t m_captureSize; @@ -1399,44 +1357,101 @@ namespace bgfx } } - void Texture::init(GLenum _target, uint8_t _format, uint8_t _numMips, uint32_t _flags) + bool Texture::init(GLenum _target, uint32_t _width, uint32_t _height, uint8_t _format, uint8_t _numMips, uint32_t _flags) { m_target = _target; m_numMips = _numMips; m_flags = _flags; m_currentFlags = UINT32_MAX; + m_width = _width; + m_height = _height; m_requestedFormat = _format; m_textureFormat = _format; - GL_CHECK(glGenTextures(1, &m_id) ); - BX_CHECK(0 != m_id, "Failed to generate texture id."); - GL_CHECK(glBindTexture(_target, m_id) ); + const bool bufferOnly = 0 != (m_flags&BGFX_TEXTURE_RT_BUFFER_ONLY); - setSamplerState(_flags); - - const TextureFormatInfo& tfi = s_textureFormat[_format]; - m_fmt = tfi.m_fmt; - m_type = tfi.m_type; - - const bool compressed = TextureFormat::Unknown > _format; - const bool decompress = !tfi.m_supported && compressed; - - if (decompress) + if (!bufferOnly) { - m_textureFormat = (uint8_t)TextureFormat::BGRA8; - const TextureFormatInfo& tfi = s_textureFormat[TextureFormat::BGRA8]; + GL_CHECK(glGenTextures(1, &m_id) ); + BX_CHECK(0 != m_id, "Failed to generate texture id."); + GL_CHECK(glBindTexture(_target, m_id) ); + + setSamplerState(_flags); + + const TextureFormatInfo& tfi = s_textureFormat[_format]; m_fmt = tfi.m_fmt; m_type = tfi.m_type; - } + + const bool compressed = TextureFormat::Unknown > _format; + const bool decompress = !tfi.m_supported && compressed; + + if (decompress) + { + m_textureFormat = (uint8_t)TextureFormat::BGRA8; + const TextureFormatInfo& tfi = s_textureFormat[TextureFormat::BGRA8]; + m_fmt = tfi.m_fmt; + m_type = tfi.m_type; + } #if BGFX_CONFIG_RENDERER_OPENGL - if (GL_RGBA == m_fmt - && s_renderCtx->m_textureSwizzleSupport) - { - GLint swizzleMask[] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; - GL_CHECK(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask) ); - } + if (GL_RGBA == m_fmt + && s_renderCtx->m_textureSwizzleSupport) + { + GLint swizzleMask[] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; + GL_CHECK(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask) ); + } #endif // BGFX_CONFIG_RENDERER_OPENGL + } + + const bool renderTarget = 0 != (m_flags&BGFX_TEXTURE_RT_MASK); + + if (renderTarget) + { + uint32_t msaaQuality = ( (m_flags&BGFX_TEXTURE_RT_MSAA_MASK)>>BGFX_TEXTURE_RT_MSAA_SHIFT); + msaaQuality = bx::uint32_satsub(msaaQuality, 1); + msaaQuality = bx::uint32_min(s_renderCtx->m_maxMsaa, msaaQuality == 0 ? 0 : 1<>BGFX_RENDER_TARGET_MSAA_SHIFT; - m_msaa = bx::uint32_min(s_renderCtx->m_maxMsaa, msaa == 0 ? 0 : 1<>BGFX_RENDER_TARGET_COLOR_SHIFT; - const uint32_t depthFormat = (_flags&BGFX_RENDER_TARGET_DEPTH_MASK)>>BGFX_RENDER_TARGET_DEPTH_SHIFT; - const GLenum minFilter = s_textureFilterMin[(_textureFlags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT][0]; - const GLenum magFilter = s_textureFilterMag[(_textureFlags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]; - - if (0 < colorFormat) + for (uint32_t ii = 0, colorIdx = 0; ii < _num; ++ii) { - m_color.createColor(colorFormat, _width, _height, minFilter, magFilter); - } + TextureHandle handle = _handles[ii]; + if (isValid(handle) ) + { + const Texture& texture = s_renderCtx->m_textures[handle.idx]; -#if 0 // GLES can't create texture with depth texture format... - if (s_renderCtx->m_depthTextureSupport - && 0 < depthFormat) - { - m_depth.createDepth(_width, _height); - } -#endif // + GLenum attachment = GL_COLOR_ATTACHMENT0 + colorIdx; + if (isDepth( (TextureFormat::Enum)texture.m_textureFormat) ) + { + attachment = GL_DEPTH_ATTACHMENT; + } + else + { + if (0 == colorIdx) + { + m_width = texture.m_width; + m_height = texture.m_height; + } -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - if (0 < colorFormat - && 0 != m_msaa) - { - GL_CHECK(glGenFramebuffers(2, m_fbo) ); - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[0]) ); + ++colorIdx; + } - GL_CHECK(glGenRenderbuffers(1, &m_colorRbo) ); - BX_CHECK(0 != m_colorRbo, "Failed to generate color renderbuffer id."); - GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_colorRbo) ); - GL_CHECK(glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaa, s_colorFormat[colorFormat].m_internalFmt, _width, _height) ); - GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0) ); - - GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER - , GL_COLOR_ATTACHMENT0 - , GL_RENDERBUFFER - , m_colorRbo - ) ); - - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[1]) ); - } - else -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - { - GL_CHECK(glGenFramebuffers(1, m_fbo) ); - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[0]) ); - } - - if (0 < colorFormat) - { - GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER - , GL_COLOR_ATTACHMENT0 - , m_color.m_target - , m_color.m_id - , 0 - ) ); + if (0 != texture.m_rbo) + { + GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER + , attachment + , GL_RENDERBUFFER + , texture.m_rbo + ) ); + } + else + { + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER + , attachment + , texture.m_target + , texture.m_id + , 0 + ) ); + } + + needResolve |= (0 != texture.m_rbo) && (0 != texture.m_id); + } } BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) @@ -2088,66 +2030,37 @@ namespace bgfx , glCheckFramebufferStatus(GL_FRAMEBUFFER) ); - if (0 < depthFormat) + if (needResolve) { - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[0]) ); + GL_CHECK(glGenFramebuffers(1, &m_fbo[1]) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[1]) ); - if (0 < colorFormat) + for (uint32_t ii = 0, colorIdx = 0; ii < _num; ++ii) { - GL_CHECK(glGenRenderbuffers(1, &m_depthRbo) ); - BX_CHECK(0 != m_depthRbo, "Failed to generate renderbuffer id."); - GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_depthRbo) ); - - const GLenum depthComponent = s_depthFormat[depthFormat].m_internalFmt; - const GLenum attachment = s_depthFormat[depthFormat].m_attachment; - -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - if (0 != m_msaa) + TextureHandle handle = _handles[ii]; + if (isValid(handle) ) { - GL_CHECK(glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaa, depthComponent, _width, _height) ); - } - else -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - { - GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, depthComponent, _width, _height) ); - } - GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0) ); + const Texture& texture = s_renderCtx->m_textures[handle.idx]; -#if BGFX_CONFIG_RENDERER_OPENGLES2 - if (GL_STENCIL_ATTACHMENT != attachment) - { - GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER - , GL_DEPTH_ATTACHMENT - , GL_RENDERBUFFER - , m_depthRbo - ) ); + if (0 != texture.m_id) + { + GLenum attachment = GL_COLOR_ATTACHMENT0 + colorIdx; + if (isDepth( (TextureFormat::Enum)texture.m_textureFormat) ) + { + attachment = GL_DEPTH_ATTACHMENT; + } + else + { + ++colorIdx; + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER + , attachment + , texture.m_target + , texture.m_id + , 0 + ) ); + } + } } - - if (GL_DEPTH_STENCIL_ATTACHMENT == attachment - || GL_STENCIL_ATTACHMENT == attachment) - { - GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER - , GL_STENCIL_ATTACHMENT - , GL_RENDERBUFFER - , m_depthRbo - ) ); - } -#else - GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER - , attachment - , GL_RENDERBUFFER - , m_depthRbo - ) ); -#endif // BGFX_CONFIG_RENDERER_OPENGLES2 - } - else - { - GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER - , GL_DEPTH_ATTACHMENT - , m_depth.m_target - , m_depth.m_id - , 0 - ) ); } BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) @@ -2159,35 +2072,20 @@ namespace bgfx GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, s_renderCtx->m_msaaBackBufferFbo) ); } - void RenderTarget::destroy() + void FrameBuffer::destroy() { GL_CHECK(glDeleteFramebuffers(0 == m_fbo[1] ? 1 : 2, m_fbo) ); memset(m_fbo, 0, sizeof(m_fbo) ); - - if (0 != m_colorRbo) - { - GL_CHECK(glDeleteRenderbuffers(1, &m_colorRbo) ); - m_colorRbo = 0; - } - - if (0 != m_depthRbo) - { - GL_CHECK(glDeleteRenderbuffers(1, &m_depthRbo) ); - m_depthRbo = 0; - } - - m_color.destroy(); - m_depth.destroy(); } - void RenderTarget::resolve() + void FrameBuffer::resolve() { #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - BX_CHECK(0 != m_fbo[1], "Can resolve without two framebuffers."); - - GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo[0]) ); - GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo[1]) ); - GL_CHECK(glBlitFramebuffer(0 + if (0 != m_fbo[1]) + { + GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo[0]) ); + GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo[1]) ); + GL_CHECK(glBlitFramebuffer(0 , 0 , m_width , m_height @@ -2198,7 +2096,8 @@ namespace bgfx , GL_COLOR_BUFFER_BIT , GL_LINEAR ) ); - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, s_renderCtx->m_msaaBackBufferFbo) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, s_renderCtx->m_msaaBackBufferFbo) ); + } #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 } @@ -2510,29 +2409,6 @@ namespace bgfx cmpFormat = (GLint*)alloca(sizeof(GLint)*numCmpFormats); GL_CHECK(glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, cmpFormat) ); -#if BGFX_CONFIG_DEBUG - static const char* s_textureFormatName[TextureFormat::Unknown+1] = - { - "BC1", - "BC2", - "BC3", - "BC4", - "BC5", - "ETC1", - "ETC2", - "ETC2A", - "ETC2A1", - "PTC12", - "PTC14", - "PTC12A", - "PTC14A", - "PTC22", - "PTC24", - "", - // TextureFormat::Count - }; -#endif // BGFX_CONFIG_DEBUG - for (GLint ii = 0; ii < numCmpFormats; ++ii) { GLint internalFmt = cmpFormat[ii]; @@ -2546,7 +2422,7 @@ namespace bgfx } } - BX_TRACE(" %3d: %8x %s", ii, internalFmt, s_textureFormatName[fmt]); + BX_TRACE(" %3d: %8x %s", ii, internalFmt, getName( (TextureFormat::Enum)fmt) ); } } @@ -2735,6 +2611,10 @@ namespace bgfx ; g_caps.maxTextureSize = glGet(GL_MAX_TEXTURE_SIZE); +#if !BGFX_CONFIG_RENDERER_OPENGLES2 + g_caps.maxFBAttachments = bx::uint32_min(glGet(GL_MAX_COLOR_ATTACHMENTS), BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS); +#endif // !BGFX_CONFIG_RENDERER_OPENGLES2 + s_renderCtx->m_vaoSupport = !!BGFX_CONFIG_RENDERER_OPENGLES3 || s_extension[Extension::ARB_vertex_array_object].m_supported || s_extension[Extension::OES_vertex_array_object].m_supported @@ -3008,14 +2888,14 @@ namespace bgfx s_renderCtx->m_textures[_handle.idx].destroy(); } - void Context::rendererCreateRenderTarget(RenderTargetHandle _handle, uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) + void Context::rendererCreateFrameBuffer(FrameBufferHandle _handle, uint8_t _num, const TextureHandle* _textureHandles) { - s_renderCtx->m_renderTargets[_handle.idx].create(_width, _height, _flags, _textureFlags); + s_renderCtx->m_frameBuffers[_handle.idx].create(_num, _textureHandles); } - void Context::rendererDestroyRenderTarget(RenderTargetHandle _handle) + void Context::rendererDestroyFrameBuffer(FrameBufferHandle _handle) { - s_renderCtx->m_renderTargets[_handle.idx].destroy(); + s_renderCtx->m_frameBuffers[_handle.idx].destroy(); } void Context::rendererCreateUniform(UniformHandle _handle, UniformType::Enum _type, uint16_t _num, const char* _name) @@ -3102,7 +2982,7 @@ namespace bgfx uint16_t programIdx = invalidHandle; SortKey key; uint8_t view = 0xff; - RenderTargetHandle rt = BGFX_INVALID_HANDLE; + FrameBufferHandle fbh = BGFX_INVALID_HANDLE; int32_t height = m_render->m_resolution.m_height; float alphaRef = 0.0f; uint32_t blendFactor = 0; @@ -3150,10 +3030,10 @@ namespace bgfx view = key.m_view; programIdx = invalidHandle; - if (m_render->m_rt[view].idx != rt.idx) + if (m_render->m_fb[view].idx != fbh.idx) { - rt = m_render->m_rt[view]; - height = s_renderCtx->setRenderTarget(rt, m_render->m_resolution.m_height); + fbh = m_render->m_fb[view]; + height = s_renderCtx->setFrameBuffer(fbh, m_render->m_resolution.m_height); } const Rect& rect = m_render->m_rect[view]; @@ -3550,20 +3430,6 @@ namespace bgfx texture.commit(stage, sampler.m_flags); } break; - - case BGFX_SAMPLER_RENDERTARGET_COLOR: - { - RenderTarget& rt = s_renderCtx->m_renderTargets[sampler.m_idx]; - rt.m_color.commit(stage, sampler.m_flags); - } - break; - - case BGFX_SAMPLER_RENDERTARGET_DEPTH: - { - RenderTarget& rt = s_renderCtx->m_renderTargets[sampler.m_idx]; - rt.m_depth.commit(stage, sampler.m_flags); - } - break; } } } @@ -3840,12 +3706,18 @@ namespace bgfx tvm.printf(0, pos++, 0x0f, "GLSL version: %s", s_renderCtx->m_glslVersion); pos = 10; - tvm.printf(10, pos++, 0x8e, " Frame CPU: %7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS%s" + tvm.printf(10, pos++, 0x8e, " Frame CPU: %7.3f, % 7.3f \x1f, % 7.3f \x1e [ms] / % 6.2f FPS " , double(frameTime)*toMs , double(min)*toMs , double(max)*toMs , freq/frameTime - , !!(m_resolution.m_flags&BGFX_RESET_VSYNC) ? " (vsync)" : "" + ); + + const uint32_t msaa = (m_resolution.m_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT; + tvm.printf(10, pos++, 0x8e, " Reset flags: [%c] vsync, [%c] MSAAx%d " + , !!(m_resolution.m_flags&BGFX_RESET_VSYNC) ? '\xfe' : ' ' + , 0 != msaa ? '\xfe' : ' ' + , 1< 3; - bool hasFragDepth = NULL != strstr(data, "gl_FragDepth"); - bool hasFrontFacing = NULL != strstr(data, "gl_FrontFacing"); + const bool hasFragCoord = NULL != strstr(data, "gl_FragCoord") || hlsl > 3; + const bool hasFragDepth = NULL != strstr(data, "gl_FragDepth"); + const bool hasFrontFacing = NULL != strstr(data, "gl_FrontFacing"); + const bool hasFragData0 = NULL != strstr(data, "gl_FragData[0]"); + const bool hasFragData1 = NULL != strstr(data, "gl_FragData[1]"); + const bool hasFragData2 = NULL != strstr(data, "gl_FragData[2]"); + const bool hasFragData3 = NULL != strstr(data, "gl_FragData[3]"); + + if (!hasFragData0 + && !hasFragData1 + && !hasFragData2 + && !hasFragData3) + { + // GL errors when both gl_FragColor and gl_FragData is used. + // This will trigger the same error with HLSL compiler too. + preprocessor.writef("#define gl_FragColor gl_FragData_0_\n"); + } preprocessor.writef("#define void_main()"); preprocessor.writef(" \\\n\tvoid main("); @@ -1733,10 +1775,22 @@ int main(int _argc, const char* _argv[]) } } - preprocessor.writef( - " \\\n\t%sout vec4 gl_FragColor : SV_TARGET" - , arg++ > 0 ? ", " : " " - ); + addFragData(preprocessor, data, 0, arg++ > 0); + + if (hasFragData1) + { + addFragData(preprocessor, data, 1, arg++ > 0); + } + + if (hasFragData2) + { + addFragData(preprocessor, data, 2, arg++ > 0); + } + + if (hasFragData3) + { + addFragData(preprocessor, data, 3, arg++ > 0); + } if (hasFragDepth) {