diff --git a/README.md b/README.md index 2838d3907..8fe7c3291 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,9 @@ point to DirectX SDK directory. setx DXSDK_DIR +If you're building with Visual Studio 2008, you'll need TR1 support from: +[Visual C++ 2008 Feature Pack Release](https://www.microsoft.com/en-us/download/details.aspx?id=6922) + If you're building with MinGW/TDM compiler on Windows make DirectX SDK directory link to directory without spaces in the path. @@ -199,6 +202,9 @@ cross-platform shaders. ### Texture Compiler (texturec) +This tool doesn't currently exist. Use nvdxt, or any other tool that produces +DDS textures for now. + ### Geometry Compiler (geometryc) Converts Wavefront .obj mesh file to format optimal for using with bgfx. @@ -208,11 +214,12 @@ Todo - Multiple render targets. - BlendFuncSeparate and BlendEquationSeparate. - - Copy from texture to texture. + - Blit between textures. - Occlusion queries. - iOS platforms. - DX11: MSAA. - GL: MSAA. + - Fullscreen mode. Notice ------ diff --git a/src/glcontext_wgl.cpp b/src/glcontext_wgl.cpp index b1c01cbec..3d3cfaed5 100644 --- a/src/glcontext_wgl.cpp +++ b/src/glcontext_wgl.cpp @@ -16,6 +16,9 @@ namespace bgfx PFNWGLMAKECURRENTPROC wglMakeCurrent; PFNWGLCREATECONTEXTPROC wglCreateContext; PFNWGLDELETECONTEXTPROC wglDeleteContext; + PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB; + PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; # define GL_IMPORT(_optional, _proto, _func) _proto _func # include "glimports.h" @@ -80,6 +83,117 @@ namespace bgfx result = wglMakeCurrent(m_hdc, m_context); BGFX_FATAL(0 != result, Fatal::UnableToInitialize, "wglMakeCurrent failed!"); + wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); + wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); + wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); + + if (NULL != wglGetExtensionsStringARB) + { + BX_TRACE("WGL extensions:"); + const char* extensions = (const char*)wglGetExtensionsStringARB(m_hdc); + if (NULL != extensions) + { + char name[1024]; + const char* pos = extensions; + const char* end = extensions + strlen(extensions); + while (pos < end) + { + uint32_t len; + const char* space = strchr(pos, ' '); + if (NULL != space) + { + len = uint32_min(sizeof(name), (uint32_t)(space - pos) ); + } + else + { + len = uint32_min(sizeof(name), (uint32_t)strlen(pos) ); + } + + strncpy(name, pos, len); + name[len] = '\0'; + + BX_TRACE("\t%s", name); + + pos += len+1; + } + } + } + +#if 0 + // An application can only set the pixel format of a window one time. + // Once a window's pixel format is set, it cannot be changed. + // MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/dd369049%28v=vs.85%29.aspx + if (NULL != wglChoosePixelFormatARB + && NULL != wglCreateContextAttribsARB) + { + int32_t attrs[] = + { + WGL_SAMPLE_BUFFERS_ARB, 0, + WGL_SAMPLES_ARB, 0, + WGL_SUPPORT_OPENGL_ARB, true, + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + WGL_DRAW_TO_WINDOW_ARB, true, + WGL_DOUBLE_BUFFER_ARB, true, + WGL_RED_BITS_ARB, 8, + WGL_BLUE_BITS_ARB, 8, + WGL_GREEN_BITS_ARB, 8, + WGL_ALPHA_BITS_ARB, 8, + WGL_DEPTH_BITS_ARB, 24, + WGL_STENCIL_BITS_ARB, 8, + 0 + }; + + uint32_t numFormats = 0; + do + { + result = wglChoosePixelFormatARB(m_hdc, attrs, NULL, 1, &pixelFormat, &numFormats); + if (0 == result + || 0 == numFormats) + { + attrs[3] >>= 1; + attrs[1] = attrs[3] == 0 ? 0 : 1; + } + + } while (0 == numFormats); + + DescribePixelFormat(m_hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + BX_TRACE("Pixel format:\n" + "\tiPixelType %d\n" + "\tcColorBits %d\n" + "\tcAlphaBits %d\n" + "\tcDepthBits %d\n" + "\tcStencilBits %d\n" + , pfd.iPixelType + , pfd.cColorBits + , pfd.cAlphaBits + , pfd.cDepthBits + , pfd.cStencilBits + ); + + result = SetPixelFormat(m_hdc, pixelFormat, &pfd); + BGFX_FATAL(0 != result, Fatal::UnableToInitialize, "SetPixelFormat failed (last err: 0x%08x)!", GetLastError() ); + + wglMakeCurrent(m_hdc, NULL); + wglDeleteContext(m_context); + + const int32_t contextAttrs[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, 2, + WGL_CONTEXT_MINOR_VERSION_ARB, 1, +#if BGFX_CONFIG_DEBUG + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, +#endif // BGFX_CONFIG_DEBUG + 0 + }; + + m_context = wglCreateContextAttribsARB(m_hdc, 0, contextAttrs); + + result = wglMakeCurrent(m_hdc, m_context); + BGFX_FATAL(0 != result, Fatal::UnableToInitialize, "wglMakeCurrent failed!"); + } +#endif // 0 + import(); } diff --git a/src/glimports.h b/src/glimports.h index b6a9cf985..89a990580 100644 --- a/src/glimports.h +++ b/src/glimports.h @@ -119,7 +119,7 @@ GL_IMPORT(true, PFNGLGETPROGRAMBINARYPROC, glGetProgramBinary); GL_IMPORT(true, PFNGLPROGRAMBINARYPROC, glProgramBinary); GL_IMPORT(true, PFNGLPROGRAMPARAMETERIPROC, glProgramParameteri); -GL_IMPORT(true, PFNGLBLITFRAMEBUFFEREXTPROC, glBlitFramebufferEXT); +GL_IMPORT(true, PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer); GL_IMPORT(true, PFNGLQUERYCOUNTERPROC, glQueryCounter); GL_IMPORT(true, PFNGLGETQUERYOBJECTI64VPROC, glGetQueryObjecti64v); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 789892215..68afb3ff3 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -452,7 +452,8 @@ namespace bgfx { if (NULL != m_swapChain) { - DX_CHECK(m_swapChain->Present(0, 0) ); + uint32_t syncInterval = !!(m_flags & BGFX_RESET_VSYNC); + DX_CHECK(m_swapChain->Present(syncInterval, 0) ); } } diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 8585ab65c..6860dd34a 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -34,6 +34,7 @@ namespace bgfx EXT_texture_sRGB, ARB_texture_swizzle, EXT_texture_swizzle, + ARB_texture_multisample, OES_standard_derivatives, ARB_get_program_binary, OES_get_program_binary, @@ -85,6 +86,7 @@ namespace bgfx { "GL_EXT_texture_sRGB", false, true }, { "GL_ARB_texture_swizzle", false, true }, { "GL_EXT_texture_swizzle", false, true }, + { "GL_ARB_texture_multisample", false, true }, { "GL_OES_standard_derivatives", false, true }, { "GL_ARB_get_program_binary", false, true }, { "GL_OES_get_program_binary", false, false }, @@ -155,16 +157,20 @@ namespace bgfx struct RendererContext { RendererContext() - : m_capture(NULL) + : m_rtMsaa(false) + , m_capture(NULL) , m_captureSize(0) , m_maxAnisotropy(0.0f) + , m_maxMsaa(0) , m_vaoSupport(false) , m_programBinarySupport(false) , m_textureSwizzleSupport(false) , m_flip(false) , m_postSwapBuffers(NULL) , m_hash( (BX_PLATFORM_WINDOWS<<1) | BX_ARCH_64BIT) + , m_backBufferFbo(0) { + m_rt.idx = invalidHandle; memset(&m_resolution, 0, sizeof(m_resolution) ); } @@ -178,12 +184,108 @@ namespace bgfx m_textVideoMem.clear(); m_resolution = _resolution; - setRenderContextSize(_resolution.m_width, _resolution.m_height); + + uint32_t msaa = 1<<( (m_resolution.m_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT); + msaa = uint32_min(m_maxMsaa, msaa == 0 ? 0 : 1<>BGFX_RENDER_TARGET_MSAA_SHIFT; + m_msaa = uint32_min(s_renderCtx.m_maxMsaa, msaa == 0 ? 0 : 1<>BGFX_RENDER_TARGET_MSAA_SHIFT]; uint32_t colorFormat = (_flags&BGFX_RENDER_TARGET_COLOR_MASK)>>BGFX_RENDER_TARGET_COLOR_SHIFT; uint32_t depthFormat = (_flags&BGFX_RENDER_TARGET_DEPTH_MASK)>>BGFX_RENDER_TARGET_DEPTH_SHIFT; GLenum minFilter = s_textureFilter[(_textureFlags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]; @@ -1491,11 +1604,35 @@ namespace bgfx { m_depth.createDepth(_width, _height); } -#endif // +#endif // - GL_CHECK(glGenFramebuffers(1, &m_fbo) ); - BX_CHECK(0 != m_fbo, "Failed to generate framebuffer id."); - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) ); +#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]) ); + + 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, GL_RGBA8, _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) { @@ -1507,8 +1644,15 @@ namespace bgfx ) ); } + BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_FRAMEBUFFER) + ); + if (0 < depthFormat) { + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo[0]) ); + if (0 < colorFormat) { #if BGFX_CONFIG_RENDERER_OPENGL @@ -1517,16 +1661,26 @@ namespace bgfx GLenum depthComponent = GL_DEPTH_COMPONENT16; #endif // BGFX_CONFIG_RENDERER_OPENGL - GL_CHECK(glGenRenderbuffers(1, &m_rbo) ); - BX_CHECK(0 != m_rbo, "Failed to generate renderbuffer id."); - GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_rbo) ); - GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, depthComponent, _width, _height) ); + GL_CHECK(glGenRenderbuffers(1, &m_depthRbo) ); + BX_CHECK(0 != m_depthRbo, "Failed to generate renderbuffer id."); + GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_depthRbo) ); + +#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + if (0 != m_msaa) + { + 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) ); GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER - , m_rbo + , m_depthRbo ) ); } else @@ -1538,29 +1692,59 @@ namespace bgfx , 0 ) ); } - } - BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) + BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) , "glCheckFramebufferStatus failed 0x%08x" , glCheckFramebufferStatus(GL_FRAMEBUFFER) ); + } - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, s_renderCtx.m_backBufferFbo) ); } void RenderTarget::destroy() { - GL_CHECK(glDeleteFramebuffers(1, &m_fbo) ); + GL_CHECK(glDeleteFramebuffers(0 == m_fbo[1] ? 1 : 2, m_fbo) ); + memset(m_fbo, 0, sizeof(m_fbo) ); - if (0 != m_rbo) + if (0 != m_colorRbo) { - GL_CHECK(glDeleteRenderbuffers(1, &m_rbo) ); + 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() + { +#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 + , 0 + , m_width + , m_height + , 0 + , 0 + , m_width + , m_height + , GL_COLOR_BUFFER_BIT + , GL_LINEAR + ) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, s_renderCtx.m_backBufferFbo) ); +#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + } + void ConstantBuffer::commit() { reset(); @@ -1845,6 +2029,13 @@ namespace bgfx glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &s_renderCtx.m_maxAnisotropy); } +#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + if (s_extension[Extension::ARB_texture_multisample].m_supported) + { + glGetIntegerv(GL_MAX_SAMPLES, &s_renderCtx.m_maxMsaa); + } +#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + if (s_extension[Extension::EXT_texture_format_BGRA8888].m_supported || s_extension[Extension::EXT_bgra].m_supported) { @@ -2038,7 +2229,7 @@ namespace bgfx GL_CHECK(glBindVertexArray(0) ); } - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, s_renderCtx.m_backBufferFbo) ); s_renderCtx.updateResolution(m_render->m_resolution); @@ -2123,18 +2314,7 @@ namespace bgfx if (m_render->m_rt[view].idx != rt.idx) { rt = m_render->m_rt[view]; - - if (rt.idx == invalidHandle) - { - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); - height = m_render->m_resolution.m_height; - } - else - { - RenderTarget& renderTarget = s_renderCtx.m_renderTargets[rt.idx]; - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.m_fbo) ); - height = renderTarget.m_height; - } + height = s_renderCtx.setRenderTarget(rt, m_render->m_resolution.m_height); } Rect& rect = m_render->m_rect[view]; @@ -2234,7 +2414,8 @@ namespace bgfx if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK |BGFX_STATE_ALPHA_MASK|BGFX_STATE_RGB_WRITE|BGFX_STATE_BLEND_MASK - |BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK|BGFX_STATE_POINT_SIZE_MASK) & changedFlags) + |BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK|BGFX_STATE_POINT_SIZE_MASK + |BGFX_STATE_MSAA) & changedFlags) { if (BGFX_STATE_CULL_MASK & changedFlags) { @@ -2297,6 +2478,18 @@ namespace bgfx float pointSize = (float)(uint32_max(1, (newFlags&BGFX_STATE_POINT_SIZE_MASK)>>BGFX_STATE_POINT_SIZE_SHIFT) ); GL_CHECK(glPointSize(pointSize) ); } + + if (BGFX_STATE_MSAA & changedFlags) + { + if (BGFX_STATE_MSAA & newFlags) + { + GL_CHECK(glEnable(GL_MULTISAMPLE) ); + } + else + { + GL_CHECK(glDisable(GL_MULTISAMPLE) ); + } + } #endif // BGFX_CONFIG_RENDERER_OPENGL if ( (BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE) & changedFlags) @@ -2761,6 +2954,8 @@ namespace bgfx } } + s_renderCtx.blitMsaaFbo(); + int64_t now = bx::getHPCounter(); elapsed += now; diff --git a/src/renderer_gl.h b/src/renderer_gl.h index d804629b8..f75d45065 100755 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -481,15 +481,26 @@ namespace bgfx struct RenderTarget { + RenderTarget() + : m_width(0) + , m_height(0) + , m_msaa(0) + { + memset(m_fbo, 0, sizeof(m_fbo) ); + } + void create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags); void destroy(); + void resolve(); GLsizei m_width; GLsizei m_height; + uint32_t m_msaa; Texture m_color; Texture m_depth; - GLuint m_fbo; - GLuint m_rbo; + GLuint m_fbo[2]; + GLuint m_colorRbo; + GLuint m_depthRbo; }; struct Program