diff --git a/README.md b/README.md index 98f2382c0..7a5e29b06 100644 --- a/README.md +++ b/README.md @@ -267,7 +267,6 @@ Todo - DX11: MSAA. - Fullscreen mode. - GL/DX11: Add support for ARB_depth_clamp, DepthBiasClamp. - - GL/GLES3: Add support for GL_ARB_sampler_objects. - Primitive scissor. Contact diff --git a/include/bgfx.h b/include/bgfx.h index 6ca2aeb6b..f069700b7 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -67,7 +67,6 @@ #define BGFX_STATE_POINT_SIZE_SHIFT 44 #define BGFX_STATE_POINT_SIZE_MASK UINT64_C(0x000ff00000000000) -#define BGFX_STATE_SRGBWRITE UINT64_C(0x0010000000000000) #define BGFX_STATE_MSAA UINT64_C(0x0020000000000000) #define BGFX_STATE_RESERVED_MASK UINT64_C(0xff00000000000000) @@ -191,7 +190,7 @@ #define BGFX_TEXTURE_MIP_POINT UINT32_C(0x00100000) #define BGFX_TEXTURE_MIP_SHIFT 20 #define BGFX_TEXTURE_MIP_MASK UINT32_C(0x00100000) -#define BGFX_TEXTURE_SRGB UINT32_C(0x00200000) +#define BGFX_TEXTURE_RESERVED_MASK UINT32_C(0xf0000000) /// #define BGFX_RENDER_TARGET_NONE UINT32_C(0x00000000) @@ -212,7 +211,6 @@ #define BGFX_RENDER_TARGET_MSAA_X16 UINT32_C(0x00040000) #define BGFX_RENDER_TARGET_MSAA_SHIFT 16 #define BGFX_RENDER_TARGET_MSAA_MASK UINT32_C(0x00070000) -#define BGFX_RENDER_TARGET_SRGBWRITE UINT32_C(0x00080000) /// #define BGFX_RESET_NONE UINT32_C(0x00000000) @@ -701,8 +699,6 @@ namespace bgfx /// BGFX_TEXTURE_[MIN/MAG/MIP]_[POINT/ANISOTROPIC] - Point or anisotropic /// sampling. /// - /// BGFX_TEXTURE_SRGB - Sample as sRGB texture. - /// /// @param _info Returns parsed DDS texture information. /// @returns Texture handle. /// @@ -830,7 +826,6 @@ namespace bgfx /// BGFX_STATE_BLEND_EQUATION_* - See NOTE 2. /// BGFX_STATE_CULL_* - Backface culling mode. /// BGFX_STATE_RGB_WRITE - Enable RGB write. - /// BGFX_STATE_SRGBWRITE - Enable sRGB write. /// BGFX_STATE_MSAA - Enable MSAA. /// BGFX_STATE_PT_[LINES/POINTS] - Primitive type. /// @@ -907,10 +902,39 @@ namespace bgfx void setProgram(ProgramHandle _handle); /// Set texture stage for draw primitive. - void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle); + /// + /// @param _stage Texture unit. + /// @param _sampler Program sampler. + /// @param _handle Texture handle. + /// @param _flags Texture sampling mode. Default value UINT32_MAX uses + /// texture sampling settings from the texture. + /// + /// BGFX_TEXTURE_[U/V/W]_[MIRROR/CLAMP] - Mirror or clamp to edge wrap + /// mode. + /// + /// BGFX_TEXTURE_[MIN/MAG/MIP]_[POINT/ANISOTROPIC] - Point or anisotropic + /// sampling. + /// + /// @param _flags Texture sampler filtering flags. UINT32_MAX use the + /// sampler filtering mode set by texture. + /// + void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint32_t _flags = UINT32_MAX); /// Set texture stage for draw primitive. - void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth = false); + /// + /// @param _stage Texture unit. + /// @param _sampler Program sampler. + /// @param _handle Render target handle. + /// @param _flags Texture sampling mode. Default value UINT32_MAX uses + /// texture sampling settings from the texture. + /// + /// BGFX_TEXTURE_[U/V/W]_[MIRROR/CLAMP] - Mirror or clamp to edge wrap + /// mode. + /// + /// BGFX_TEXTURE_[MIN/MAG/MIP]_[POINT/ANISOTROPIC] - Point or anisotropic + /// sampling. + /// + void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth = false, uint32_t _flags = UINT32_MAX); /// Submit primitive for rendering into single view. /// diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 5969c045c..dc2def0d2 100755 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -1472,16 +1472,16 @@ namespace bgfx s_ctx.m_submit->setProgram(_handle); } - void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle) + void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint32_t _flags) { BGFX_CHECK_MAIN_THREAD(); - s_ctx.m_submit->setTexture(_stage, _sampler, _handle); + s_ctx.m_submit->setTexture(_stage, _sampler, _handle, _flags); } - void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth) + void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth, uint32_t _flags) { BGFX_CHECK_MAIN_THREAD(); - s_ctx.m_submit->setTexture(_stage, _sampler, _handle, _depth); + s_ctx.m_submit->setTexture(_stage, _sampler, _handle, _depth, _flags); } void submit(uint8_t _id, int32_t _depth) diff --git a/src/bgfx_p.h b/src/bgfx_p.h index f6a1129c3..a98584e25 100755 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -131,10 +131,11 @@ namespace stl { #define BGFX_STATE_TEX_MASK UINT64_C(0xff00000000000000) #define BGFX_STATE_TEX_COUNT 8 -#define BGFX_SAMPLER_TEXTURE UINT16_C(0x0000) -#define BGFX_SAMPLER_RENDERTARGET_COLOR UINT16_C(0x0001) -#define BGFX_SAMPLER_RENDERTARGET_DEPTH UINT16_C(0x0002) -#define BGFX_SAMPLER_TYPE_MASK UINT16_C(0x0003) +#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 # define BGFX_RENDERER_NAME "Direct3D 9" @@ -651,8 +652,8 @@ namespace bgfx struct Sampler { + uint32_t m_flags; uint16_t m_idx; - uint16_t m_flags; }; struct Uniform @@ -1084,12 +1085,15 @@ namespace bgfx m_key.m_program = _handle.idx; } - void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle) + void setTexture(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint32_t _flags) { m_flags |= BGFX_STATE_TEX0<<_stage; Sampler& sampler = m_state.m_sampler[_stage]; sampler.m_idx = _handle.idx; - sampler.m_flags = BGFX_SAMPLER_TEXTURE; + sampler.m_flags = 0 + | BGFX_SAMPLER_TEXTURE + | ( (_flags&BGFX_SAMPLER_TYPE_MASK) ? BGFX_SAMPLER_DEFAULT_FLAGS : _flags) + ; if (invalidHandle != _sampler.idx) { @@ -1098,12 +1102,15 @@ namespace bgfx } } - void setTexture(uint8_t _stage, UniformHandle _sampler, RenderTargetHandle _handle, bool _depth) + 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 = _depth ? BGFX_SAMPLER_RENDERTARGET_DEPTH : BGFX_SAMPLER_RENDERTARGET_COLOR; + sampler.m_flags = 0 + | (_depth ? BGFX_SAMPLER_RENDERTARGET_DEPTH : BGFX_SAMPLER_RENDERTARGET_COLOR) + | ( (_flags&BGFX_SAMPLER_TYPE_MASK) ? BGFX_SAMPLER_DEFAULT_FLAGS : _flags) + ; if (invalidHandle != _sampler.idx) { diff --git a/src/glimports.h b/src/glimports.h index ced628db5..7c6c1fa08 100644 --- a/src/glimports.h +++ b/src/glimports.h @@ -143,6 +143,12 @@ GL_IMPORT(true, PFNGLDEBUGMESSAGEINSERTARBPROC, glDebugMessageInsertAR GL_IMPORT(true, PFNGLDEBUGMESSAGECALLBACKARBPROC, glDebugMessageCallbackARB); GL_IMPORT(true, PFNGLGETDEBUGMESSAGELOGARBPROC, glGetDebugMessageLogARB); +GL_IMPORT(true, PFNGLGENSAMPLERSPROC, glGenSamplers); +GL_IMPORT(true, PFNGLDELETESAMPLERSPROC, glDeleteSamplers); +GL_IMPORT(true, PFNGLBINDSAMPLERPROC, glBindSampler); +GL_IMPORT(true, PFNGLSAMPLERPARAMETERIPROC, glSamplerParameteri); +GL_IMPORT(true, PFNGLSAMPLERPARAMETERFPROC, glSamplerParameterf); + #if BGFX_CONFIG_DEBUG_GREMEDY GL_IMPORT(true, PFNGLSTRINGMARKERGREMEDYPROC, glStringMarkerGREMEDY); GL_IMPORT(true, PFNGLFRAMETERMINATORGREMEDYPROC, glFrameTerminatorGREMEDY); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 263b7cd8c..ba614115d 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -12,8 +12,6 @@ namespace bgfx { static wchar_t s_viewNameW[BGFX_CONFIG_MAX_VIEWS][256]; - typedef HRESULT (WINAPI * PFN_CREATEDXGIFACTORY)(REFIID _riid, void** _factory); - static const D3D11_PRIMITIVE_TOPOLOGY s_primType[] = { D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST, @@ -939,33 +937,32 @@ namespace bgfx | BGFX_TEXTURE_U_MASK|BGFX_TEXTURE_V_MASK|BGFX_TEXTURE_W_MASK ; - uint8_t minFilter = s_textureFilter[0][(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]; - uint8_t magFilter = s_textureFilter[1][(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]; - uint8_t mipFilter = s_textureFilter[2][(_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT]; - - D3D11_SAMPLER_DESC sd; - sd.Filter = (D3D11_FILTER)(minFilter|magFilter|mipFilter); - sd.AddressU = s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]; - sd.AddressV = s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]; - sd.AddressW = s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]; - sd.MipLODBias = 0.0f; - sd.MaxAnisotropy = 1; - sd.ComparisonFunc = D3D11_COMPARISON_NEVER; - sd.BorderColor[0] = 0.0f; - sd.BorderColor[1] = 0.0f; - sd.BorderColor[2] = 0.0f; - sd.BorderColor[3] = 0.0f; - sd.MinLOD = 0; - sd.MaxLOD = D3D11_FLOAT32_MAX; - uint32_t hash = bx::hashMurmur2A(sd); - - ID3D11SamplerState* sampler = m_samplerStateCache.find(hash); + ID3D11SamplerState* sampler = m_samplerStateCache.find(_flags); if (NULL == sampler) { + uint8_t minFilter = s_textureFilter[0][(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]; + uint8_t magFilter = s_textureFilter[1][(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]; + uint8_t mipFilter = s_textureFilter[2][(_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT]; + + D3D11_SAMPLER_DESC sd; + sd.Filter = (D3D11_FILTER)(minFilter|magFilter|mipFilter); + sd.AddressU = s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]; + sd.AddressV = s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]; + sd.AddressW = s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]; + sd.MipLODBias = 0.0f; + sd.MaxAnisotropy = 1; + sd.ComparisonFunc = D3D11_COMPARISON_NEVER; + sd.BorderColor[0] = 0.0f; + sd.BorderColor[1] = 0.0f; + sd.BorderColor[2] = 0.0f; + sd.BorderColor[3] = 0.0f; + sd.MinLOD = 0; + sd.MaxLOD = D3D11_FLOAT32_MAX; + m_device->CreateSamplerState(&sd, &sampler); DX_CHECK_REFCOUNT(sampler, 1); - m_samplerStateCache.add(hash, sampler); + m_samplerStateCache.add(_flags, sampler); } return sampler; @@ -1962,10 +1959,14 @@ namespace bgfx DX_RELEASE(m_ptr, 0); } - void Texture::commit(uint8_t _stage) + void Texture::commit(uint8_t _stage, uint32_t _flags) { - s_renderCtx.m_textureStage.m_srv[_stage] = m_srv; - s_renderCtx.m_textureStage.m_sampler[_stage] = m_sampler; + 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, const Memory* _mem) @@ -2060,10 +2061,14 @@ namespace bgfx m_flags = 0; } - void RenderTarget::commit(uint8_t _stage) + void RenderTarget::commit(uint8_t _stage, uint32_t _flags) { - s_renderCtx.m_textureStage.m_srv[_stage] = m_srv; - s_renderCtx.m_textureStage.m_sampler[_stage] = m_sampler; + 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 UniformBuffer::create(UniformType::Enum _type, uint16_t _num, bool _alloc) @@ -2418,7 +2423,6 @@ namespace bgfx | BGFX_STATE_ALPHA_REF_MASK | BGFX_STATE_PT_MASK | BGFX_STATE_POINT_SIZE_MASK - | BGFX_STATE_SRGBWRITE | BGFX_STATE_MSAA ) & changedFlags) { @@ -2629,15 +2633,23 @@ namespace bgfx switch (sampler.m_flags&BGFX_SAMPLER_TYPE_MASK) { case BGFX_SAMPLER_TEXTURE: - s_renderCtx.m_textures[sampler.m_idx].commit(stage); + { + Texture& texture = s_renderCtx.m_textures[sampler.m_idx]; + texture.commit(stage, sampler.m_flags); + } break; case BGFX_SAMPLER_RENDERTARGET_COLOR: - s_renderCtx.m_renderTargets[sampler.m_idx].commit(stage); + { + 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; + { +// id = s_renderCtx.m_renderTargets[sampler.m_idx].m_depth.m_id; + } break; } } diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index 79e1fefdf..641ccb704 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -15,6 +15,8 @@ namespace bgfx { + typedef HRESULT (WINAPI * PFN_CREATEDXGIFACTORY)(REFIID _riid, void** _factory); + template class StateCacheT { @@ -235,7 +237,6 @@ namespace bgfx : m_ptr(NULL) , m_srv(NULL) , m_sampler(NULL) - , m_srgb(false) , m_numMips(0) { } @@ -243,7 +244,7 @@ namespace bgfx void create(const Memory* _mem, uint32_t _flags); void destroy(); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, const Memory* _mem); - void commit(uint8_t _stage); + void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS); union { @@ -255,7 +256,6 @@ namespace bgfx ID3D11ShaderResourceView* m_srv; ID3D11SamplerState* m_sampler; Enum m_type; - bool m_srgb; uint8_t m_numMips; }; @@ -267,8 +267,6 @@ namespace bgfx , m_rtv(NULL) , m_dsv(NULL) , m_srv(NULL) -// , m_minFilter(D3DTEXF_LINEAR) -// , m_magFilter(D3DTEXF_LINEAR) , m_width(0) , m_height(0) , m_flags(0) @@ -278,18 +276,7 @@ namespace bgfx void create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags); void destroy(); - - void commit(uint8_t _stage); -// void resolve(); - -// Msaa m_msaa; -// IDirect3DSurface9* m_rt; -// IDirect3DTexture9* m_colorTexture; -// IDirect3DSurface9* m_color; -// IDirect3DTexture9* m_depthTexture; -// IDirect3DSurface9* m_depth; -// D3DTEXTUREFILTERTYPE m_minFilter; -// D3DTEXTUREFILTERTYPE m_magFilter; + void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS); ID3D11Texture2D* m_colorTexture; ID3D11Texture2D* m_depthTexture; diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 54fd98151..232c481f6 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -677,6 +677,8 @@ namespace bgfx void preReset() { + invalidateSamplerState(); + for (uint32_t stage = 0; stage < BGFX_STATE_TEX_COUNT; ++stage) { DX_CHECK(m_device->SetTexture(stage, NULL) ); @@ -733,6 +735,36 @@ namespace bgfx } } + void invalidateSamplerState() + { + for (uint32_t stage = 0; stage < BGFX_STATE_TEX_COUNT; ++stage) + { + m_samplerFlags[stage] = UINT32_MAX; + } + } + + void setSamplerState(uint8_t _stage, uint32_t _flags) + { + const uint32_t flags = _flags&(~BGFX_TEXTURE_RESERVED_MASK); + if (m_samplerFlags[_stage] != flags) + { + m_samplerFlags[_stage] = flags; + IDirect3DDevice9* device = m_device; + D3DTEXTUREADDRESS tau = s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]; + D3DTEXTUREADDRESS tav = s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]; + D3DTEXTUREADDRESS taw = s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]; + D3DTEXTUREFILTERTYPE minFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]; + D3DTEXTUREFILTERTYPE magFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]; + D3DTEXTUREFILTERTYPE mipFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT]; + DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_ADDRESSU, tau) ); + DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_ADDRESSV, tav) ); + DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_MINFILTER, minFilter) ); + DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_MAGFILTER, magFilter) ); + DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_MIPFILTER, mipFilter) ); + DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_ADDRESSW, taw) ); + } + } + void capturePreReset() { if (NULL != m_captureSurface) @@ -917,6 +949,8 @@ namespace bgfx UniformRegistry m_uniformReg; void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; + uint32_t m_samplerFlags[BGFX_STATE_TEX_COUNT]; + Texture* m_updateTexture; uint8_t* m_updateTextureBits; uint32_t m_updateTexturePitch; @@ -1433,13 +1467,7 @@ namespace bgfx void Texture::create(const Memory* _mem, uint32_t _flags) { - m_tau = s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]; - m_tav = s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]; - m_taw = s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]; - m_minFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]; - m_magFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]; - m_mipFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT]; - m_srgb = (_flags&BGFX_TEXTURE_SRGB) == BGFX_TEXTURE_SRGB; + m_flags = _flags; Dds dds; @@ -1673,22 +1701,10 @@ namespace bgfx unlock(s_renderCtx.m_updateTextureSide, s_renderCtx.m_updateTextureMip); } - void Texture::commit(uint8_t _stage) + void Texture::commit(uint8_t _stage, uint32_t _flags) { - IDirect3DDevice9* device = s_renderCtx.m_device; - DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_MINFILTER, m_minFilter) ); - DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_MAGFILTER, m_magFilter) ); - DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_MIPFILTER, m_mipFilter) ); - DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_ADDRESSU, m_tau) ); - DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_ADDRESSV, m_tav) ); - if (m_type == Texture3D) - { - DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_ADDRESSW, m_taw) ); - } -#if BX_PLATFORM_WINDOWS - DX_CHECK(device->SetSamplerState(_stage, D3DSAMP_SRGBTEXTURE, m_srgb) ); -#endif // BX_PLATFORM_WINDOWS - DX_CHECK(device->SetTexture(_stage, m_ptr) ); + s_renderCtx.setSamplerState(_stage, 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) ? _flags : m_flags); + 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) @@ -1696,8 +1712,10 @@ namespace bgfx m_width = _width; m_height = _height; m_flags = _flags; - m_minFilter = s_textureFilter[(_textureFlags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]; - m_magFilter = s_textureFilter[(_textureFlags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]; + m_textureFlags = (_textureFlags&(BGFX_TEXTURE_MIN_MASK|BGFX_TEXTURE_MAG_MASK) ) + | BGFX_TEXTURE_U_CLAMP + | BGFX_TEXTURE_V_CLAMP + ; createTextures(); } @@ -1828,16 +1846,9 @@ namespace bgfx } } - void RenderTarget::commit(uint8_t _stage) + void RenderTarget::commit(uint8_t _stage, uint32_t _textureFlags) { - DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_MINFILTER, m_minFilter) ); - DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_MAGFILTER, m_magFilter) ); - DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_MIPFILTER, D3DTEXF_POINT) ); - DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP) ); - DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP) ); -#if BX_PLATFORM_WINDOWS - DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_SRGBTEXTURE, (m_flags&BGFX_RENDER_TARGET_SRGBWRITE) == BGFX_RENDER_TARGET_SRGBWRITE) ); -#endif // BX_PLATFORM_WINDOWS + 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) ); } @@ -2221,6 +2232,8 @@ namespace bgfx uint32_t statsNumInstances = 0; uint32_t statsNumPrimsRendered = 0; + s_renderCtx.invalidateSamplerState(); + if (0 == (m_render->m_debug&BGFX_DEBUG_IFH) ) { for (uint32_t item = 0, numItems = m_render->m_num; item < numItems; ++item) @@ -2393,7 +2406,6 @@ namespace bgfx | BGFX_STATE_ALPHA_REF_MASK | BGFX_STATE_PT_MASK | BGFX_STATE_POINT_SIZE_MASK - | BGFX_STATE_SRGBWRITE | BGFX_STATE_MSAA ) & changedFlags) { @@ -2430,13 +2442,6 @@ namespace bgfx DX_CHECK(device->SetRenderState(D3DRS_POINTSIZE, castfu( (float)( (newFlags&BGFX_STATE_POINT_SIZE_MASK)>>BGFX_STATE_POINT_SIZE_SHIFT) ) ) ); } -#if BX_PLATFORM_WINDOWS - if (BGFX_STATE_SRGBWRITE & changedFlags) - { - DX_CHECK(device->SetRenderState(D3DRS_SRGBWRITEENABLE, (newFlags&BGFX_STATE_SRGBWRITE) == BGFX_STATE_SRGBWRITE) ); - } -#endif // BX_PLATFORM_WINDOWS - if (BGFX_STATE_MSAA & changedFlags) { DX_CHECK(device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, (newFlags&BGFX_STATE_MSAA) == BGFX_STATE_MSAA) ); @@ -2651,11 +2656,11 @@ namespace bgfx switch (sampler.m_flags&BGFX_SAMPLER_TYPE_MASK) { case BGFX_SAMPLER_TEXTURE: - s_renderCtx.m_textures[sampler.m_idx].commit(stage); + 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); + s_renderCtx.m_renderTargets[sampler.m_idx].commit(stage, sampler.m_flags); break; case BGFX_SAMPLER_RENDERTARGET_DEPTH: diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index 504b007c6..c043d6dd5 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -310,7 +310,7 @@ namespace bgfx 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, const Memory* _mem); void updateEnd(); - void commit(uint8_t _stage); + void commit(uint8_t _stage, uint32_t _flags = BGFX_SAMPLER_DEFAULT_FLAGS); union { @@ -320,15 +320,9 @@ namespace bgfx IDirect3DCubeTexture9* m_textureCube; }; - D3DTEXTUREFILTERTYPE m_minFilter; - D3DTEXTUREFILTERTYPE m_magFilter; - D3DTEXTUREFILTERTYPE m_mipFilter; - D3DTEXTUREADDRESS m_tau; - D3DTEXTUREADDRESS m_tav; - D3DTEXTUREADDRESS m_taw; + uint32_t m_flags; TextureFormat::Enum m_format; Enum m_type; - bool m_srgb; }; struct RenderTarget @@ -339,8 +333,6 @@ namespace bgfx , m_color(NULL) , m_depthTexture(NULL) , m_depth(NULL) - , m_minFilter(D3DTEXF_LINEAR) - , m_magFilter(D3DTEXF_LINEAR) , m_width(0) , m_height(0) , m_flags(0) @@ -368,7 +360,7 @@ namespace bgfx createTextures(); } - void commit(uint8_t _stage); + void commit(uint8_t _stage, uint32_t _textureFlags = BGFX_SAMPLER_DEFAULT_FLAGS); void resolve(); Msaa m_msaa; @@ -377,11 +369,10 @@ namespace bgfx IDirect3DSurface9* m_color; IDirect3DTexture9* m_depthTexture; IDirect3DSurface9* m_depth; - D3DTEXTUREFILTERTYPE m_minFilter; - D3DTEXTUREFILTERTYPE m_magFilter; uint16_t m_width; uint16_t m_height; uint32_t m_flags; + uint32_t m_textureFlags; bool m_depthOnly; }; diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index b7db95c3d..7f0af469a 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -14,6 +14,204 @@ namespace bgfx { static char s_viewName[BGFX_CONFIG_MAX_VIEWS][256]; + static const GLenum s_primType[] = + { + GL_TRIANGLES, + GL_LINES, + GL_POINTS, + }; + + static const char* s_attribName[Attrib::Count] = + { + "a_position", + "a_normal", + "a_tangent", + "a_color0", + "a_color1", + "a_indices", + "a_weight", + "a_texcoord0", + "a_texcoord1", + "a_texcoord2", + "a_texcoord3", + "a_texcoord4", + "a_texcoord5", + "a_texcoord6", + "a_texcoord7", + }; + + static const char* s_instanceDataName[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT] = + { + "i_data0", + "i_data1", + "i_data2", + "i_data3", + "i_data4", + }; + + static const GLenum s_attribType[AttribType::Count] = + { + GL_UNSIGNED_BYTE, + GL_SHORT, + GL_HALF_FLOAT, + GL_FLOAT, + }; + + struct Blend + { + GLenum m_src; + GLenum m_dst; + bool m_factor; + }; + + static const Blend s_blendFactor[] = + { + { 0, 0, false }, // ignored + { GL_ZERO, GL_ZERO, false }, + { GL_ONE, GL_ONE, false }, + { GL_SRC_COLOR, GL_SRC_COLOR, false }, + { GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, false }, + { GL_SRC_ALPHA, GL_SRC_ALPHA, false }, + { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, false }, + { GL_DST_ALPHA, GL_DST_ALPHA, false }, + { GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, false }, + { GL_DST_COLOR, GL_DST_COLOR, false }, + { GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_DST_COLOR, false }, + { GL_SRC_ALPHA_SATURATE, GL_ONE, false }, + { GL_CONSTANT_COLOR, GL_CONSTANT_COLOR, true }, + { GL_ONE_MINUS_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, true }, + }; + + static const GLenum s_blendEquation[] = + { + GL_FUNC_ADD, + GL_FUNC_SUBTRACT, + GL_FUNC_REVERSE_SUBTRACT, + GL_MIN, + GL_MAX, + }; + + static const GLenum s_depthFunc[] = + { + 0, // ignored + GL_LESS, + GL_LEQUAL, + GL_EQUAL, + GL_GEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_NEVER, + GL_ALWAYS, + }; + + static const GLenum s_stencilFunc[] = + { + 0, // ignored + GL_LESS, + GL_LEQUAL, + GL_EQUAL, + GL_GEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_NEVER, + GL_ALWAYS, + }; + + static const GLenum s_stencilOp[] = + { + GL_ZERO, + GL_KEEP, + GL_REPLACE, + GL_INCR_WRAP, + GL_INCR, + GL_DECR_WRAP, + GL_DECR, + GL_INVERT, + }; + + static const GLenum s_stencilFace[] = + { + GL_FRONT_AND_BACK, + GL_FRONT, + 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 }, + }; + + static const GLenum s_depthFormat[] = + { + 0, // ignored + 0, + }; + + static const GLenum s_textureAddress[] = + { + GL_REPEAT, + GL_MIRRORED_REPEAT, + GL_CLAMP_TO_EDGE, + }; + + static const GLenum s_textureFilterMag[] = + { + GL_LINEAR, + GL_NEAREST, + GL_LINEAR, + }; + + static const GLenum s_textureFilterMin[][3] = + { + { GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_LINEAR }, + { GL_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_NEAREST }, + { GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_LINEAR }, + }; + + struct TextureFormatInfo + { + GLenum m_internalFmt; + GLenum m_fmt; + GLenum m_type; + uint8_t m_bpp; + bool m_supported; + }; + + static TextureFormatInfo s_textureFormat[TextureFormat::Count] = + { + { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, 4, false }, + { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, 8, false }, + { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, 8, false }, + { GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_ZERO, 4, false }, + { GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_ZERO, 8, false }, + { GL_ZERO, GL_ZERO, GL_ZERO, 0, true }, + { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, true }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, true }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, true }, + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_BYTE, 64, true }, + { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 64, true }, + { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, true }, + { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, true }, + { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, true }, + { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, 32, true }, + }; + struct Extension { enum Enum @@ -26,6 +224,7 @@ namespace bgfx ARB_half_float_vertex, ARB_instanced_arrays, ARB_multisample, + ARB_sampler_objects, ARB_seamless_cube_map, ARB_texture_float, ARB_texture_multisample, @@ -85,6 +284,7 @@ namespace bgfx { "GL_ARB_half_float_vertex", false, true }, { "GL_ARB_instanced_arrays", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, { "GL_ARB_multisample", false, true }, + { "GL_ARB_sampler_objects", BGFX_CONFIG_RENDERER_OPENGL >= 31, true }, { "GL_ARB_seamless_cube_map", BGFX_CONFIG_RENDERER_OPENGL >= 31, true }, { "GL_ARB_texture_float", BGFX_CONFIG_RENDERER_OPENGL >= 31, true }, { "GL_ARB_texture_multisample", false, true }, @@ -467,8 +667,52 @@ namespace bgfx { if (m_vaoSupport) { - m_vaoCache.invalidate(); + m_vaoStateCache.invalidate(); } + +#if !BGFX_CONFIG_RENDERER_OPENGLES2 + if (m_samplerObjectSupport) + { + m_samplerStateCache.invalidate(); + } +#endif // !BGFX_CONFIG_RENDERER_OPENGLES2 + } + + void setSamplerState(uint32_t _stage, uint32_t _numMips, uint32_t _flags) + { +#if !BGFX_CONFIG_RENDERER_OPENGLES2 + if (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) ) + { + GLuint sampler = m_samplerStateCache.find(_flags); + + if (UINT32_MAX == sampler) + { + sampler = m_samplerStateCache.add(_flags); + + GL_CHECK(glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]) ); + GL_CHECK(glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]) ); + GL_CHECK(glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]) ); + + uint32_t mag = (_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT; + uint32_t min = (_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT; + uint32_t mip = (_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT; + GLenum minFilter = s_textureFilterMin[min][1 < _numMips ? mip+1 : 0]; + GL_CHECK(glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, s_textureFilterMag[mag]) ); + GL_CHECK(glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, minFilter) ); + if (0 != (_flags & (BGFX_TEXTURE_MIN_ANISOTROPIC|BGFX_TEXTURE_MAG_ANISOTROPIC) ) + && 0.0f < m_maxAnisotropy) + { + GL_CHECK(glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_maxAnisotropy) ); + } + } + + GL_CHECK(glBindSampler(_stage, sampler) ); + } + else + { + GL_CHECK(glBindSampler(_stage, 0) ); + } +#endif // !BGFX_CONFIG_RENDERER_OPENGLES2 } void updateCapture() @@ -594,7 +838,10 @@ namespace bgfx Queries m_queries; #endif // BGFX_CONFIG_RENDERER_OPENGL - VaoCache m_vaoCache; + VaoStateCache m_vaoStateCache; +#if !BGFX_CONFIG_RENDERER_OPENGLES2 + SamplerStateCache m_samplerStateCache; +#endif // !BGFX_CONFIG_RENDERER_OPENGLES2 TextVideoMem m_textVideoMem; RenderTargetHandle m_rt; @@ -607,6 +854,7 @@ namespace bgfx int32_t m_maxMsaa; GLuint m_vao; bool m_vaoSupport; + bool m_samplerObjectSupport; bool m_programBinarySupport; bool m_textureSwizzleSupport; bool m_useClearQuad; @@ -667,204 +915,6 @@ namespace bgfx } #endif // BX_PLATFORM_ - static const GLenum s_primType[] = - { - GL_TRIANGLES, - GL_LINES, - GL_POINTS, - }; - - static const char* s_attribName[Attrib::Count] = - { - "a_position", - "a_normal", - "a_tangent", - "a_color0", - "a_color1", - "a_indices", - "a_weight", - "a_texcoord0", - "a_texcoord1", - "a_texcoord2", - "a_texcoord3", - "a_texcoord4", - "a_texcoord5", - "a_texcoord6", - "a_texcoord7", - }; - - static const char* s_instanceDataName[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT] = - { - "i_data0", - "i_data1", - "i_data2", - "i_data3", - "i_data4", - }; - - static const GLenum s_attribType[AttribType::Count] = - { - GL_UNSIGNED_BYTE, - GL_SHORT, - GL_HALF_FLOAT, - GL_FLOAT, - }; - - struct Blend - { - GLenum m_src; - GLenum m_dst; - bool m_factor; - }; - - static const Blend s_blendFactor[] = - { - { 0, 0, false }, // ignored - { GL_ZERO, GL_ZERO, false }, - { GL_ONE, GL_ONE, false }, - { GL_SRC_COLOR, GL_SRC_COLOR, false }, - { GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, false }, - { GL_SRC_ALPHA, GL_SRC_ALPHA, false }, - { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, false }, - { GL_DST_ALPHA, GL_DST_ALPHA, false }, - { GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, false }, - { GL_DST_COLOR, GL_DST_COLOR, false }, - { GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_DST_COLOR, false }, - { GL_SRC_ALPHA_SATURATE, GL_ONE, false }, - { GL_CONSTANT_COLOR, GL_CONSTANT_COLOR, true }, - { GL_ONE_MINUS_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, true }, - }; - - static const GLenum s_blendEquation[] = - { - GL_FUNC_ADD, - GL_FUNC_SUBTRACT, - GL_FUNC_REVERSE_SUBTRACT, - GL_MIN, - GL_MAX, - }; - - static const GLenum s_depthFunc[] = - { - 0, // ignored - GL_LESS, - GL_LEQUAL, - GL_EQUAL, - GL_GEQUAL, - GL_GREATER, - GL_NOTEQUAL, - GL_NEVER, - GL_ALWAYS, - }; - - static const GLenum s_stencilFunc[] = - { - 0, // ignored - GL_LESS, - GL_LEQUAL, - GL_EQUAL, - GL_GEQUAL, - GL_GREATER, - GL_NOTEQUAL, - GL_NEVER, - GL_ALWAYS, - }; - - static const GLenum s_stencilOp[] = - { - GL_ZERO, - GL_KEEP, - GL_REPLACE, - GL_INCR_WRAP, - GL_INCR, - GL_DECR_WRAP, - GL_DECR, - GL_INVERT, - }; - - static const GLenum s_stencilFace[] = - { - GL_FRONT_AND_BACK, - GL_FRONT, - 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 }, - }; - - static const GLenum s_depthFormat[] = - { - 0, // ignored - 0, - }; - - static const GLenum s_textureAddress[] = - { - GL_REPEAT, - GL_MIRRORED_REPEAT, - GL_CLAMP_TO_EDGE, - }; - - static const GLenum s_textureFilterMag[] = - { - GL_LINEAR, - GL_NEAREST, - GL_LINEAR, - }; - - static const GLenum s_textureFilterMin[][3] = - { - { GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_LINEAR }, - { GL_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_NEAREST }, - { GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_LINEAR }, - }; - - struct TextureFormatInfo - { - GLenum m_internalFmt; - GLenum m_fmt; - GLenum m_type; - uint8_t m_bpp; - bool m_supported; - }; - - static TextureFormatInfo s_textureFormat[TextureFormat::Count] = - { - { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, 4, false }, - { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, 8, false }, - { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, 8, false }, - { GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_ZERO, 4, false }, - { GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_ZERO, 8, false }, - { GL_ZERO, GL_ZERO, GL_ZERO, 0, true }, - { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, true }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, true }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, true }, - { GL_RGBA16, GL_RGBA, GL_UNSIGNED_BYTE, 64, true }, - { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 64, true }, - { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, true }, - { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, true }, - { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, true }, - { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, 32, true }, - }; - const char* glslTypeName(GLuint _type) { #define GLSL_TYPE(_ty) case _ty: return #_ty @@ -1042,7 +1092,7 @@ namespace bgfx GL_CHECK(glUseProgram(0) ); GL_CHECK(glDeleteProgram(m_id) ); - m_vcref.invalidate(s_renderCtx.m_vaoCache); + m_vcref.invalidate(s_renderCtx.m_vaoStateCache); } void Program::init() @@ -1245,7 +1295,7 @@ namespace bgfx GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); GL_CHECK(glDeleteBuffers(1, &m_id) ); - m_vcref.invalidate(s_renderCtx.m_vaoCache); + m_vcref.invalidate(s_renderCtx.m_vaoStateCache); } void VertexBuffer::destroy() @@ -1253,7 +1303,7 @@ namespace bgfx GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); GL_CHECK(glDeleteBuffers(1, &m_id) ); - m_vcref.invalidate(s_renderCtx.m_vaoCache); + m_vcref.invalidate(s_renderCtx.m_vaoStateCache); } static void texImage(GLenum _target, GLint _level, GLint _internalFormat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLenum _format, GLenum _type, const GLvoid* _pixels) @@ -1325,34 +1375,15 @@ namespace bgfx void Texture::init(GLenum _target, uint8_t _numMips, uint32_t _flags) { m_target = _target; + m_numMips = _numMips; + m_flags = _flags; + m_currentFlags = UINT32_MAX; GL_CHECK(glGenTextures(1, &m_id) ); BX_CHECK(0 != m_id, "Failed to generate texture id."); GL_CHECK(glBindTexture(_target, m_id) ); - GL_CHECK(glTexParameteri(_target, GL_TEXTURE_WRAP_S, s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]) ); - GL_CHECK(glTexParameteri(_target, GL_TEXTURE_WRAP_T, s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]) ); - -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - GL_CHECK(glTexParameteri(_target, GL_TEXTURE_MAX_LEVEL, _numMips-1) ); - - if (_target == GL_TEXTURE_3D) - { - GL_CHECK(glTexParameteri(_target, GL_TEXTURE_WRAP_R, s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]) ); - } -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - - uint32_t mag = (_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT; - uint32_t min = (_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT; - uint32_t mip = (_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT; - GLenum minFilter = s_textureFilterMin[min][1 < _numMips ? mip+1 : 0]; - GL_CHECK(glTexParameteri(_target, GL_TEXTURE_MAG_FILTER, s_textureFilterMag[mag]) ); - GL_CHECK(glTexParameteri(_target, GL_TEXTURE_MIN_FILTER, minFilter) ); - if (0 != (_flags & (BGFX_TEXTURE_MIN_ANISOTROPIC|BGFX_TEXTURE_MAG_ANISOTROPIC) ) - && 0.0f < s_renderCtx.m_maxAnisotropy) - { - GL_CHECK(glTexParameterf(_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, s_renderCtx.m_maxAnisotropy) ); - } + setSamplerState(_flags); } void Texture::create(const Memory* _mem, uint32_t _flags) @@ -1635,6 +1666,9 @@ namespace bgfx GLenum internalFormat = rtcf.m_internalFmt; GLenum type = rtcf.m_type; m_target = GL_TEXTURE_2D; + m_numMips = 1; +// m_flags = _flags; + m_currentFlags = UINT32_MAX; GL_CHECK(glGenTextures(1, &m_id) ); BX_CHECK(0 != m_id, "Failed to generate texture id."); @@ -1666,6 +1700,7 @@ namespace bgfx void Texture::createDepth(uint32_t _width, uint32_t _height) { m_target = GL_TEXTURE_2D; + m_numMips = 1; GL_CHECK(glGenTextures(1, &m_id) ); BX_CHECK(0 != m_id, "Failed to generate texture id."); @@ -1812,6 +1847,67 @@ namespace bgfx } } + void Texture::setSamplerState(uint32_t _flags) + { + const uint32_t flags = _flags&(~BGFX_TEXTURE_RESERVED_MASK); + if ( (0 != (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) && m_flags != m_currentFlags) + || m_currentFlags != flags) + { + const GLenum target = m_target; + const uint8_t numMips = m_numMips; + + GL_CHECK(glTexParameteri(target, GL_TEXTURE_WRAP_S, s_textureAddress[(flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]) ); + GL_CHECK(glTexParameteri(target, GL_TEXTURE_WRAP_T, s_textureAddress[(flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]) ); + +#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + GL_CHECK(glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, numMips-1) ); + + if (target == GL_TEXTURE_3D) + { + GL_CHECK(glTexParameteri(target, GL_TEXTURE_WRAP_R, s_textureAddress[(flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]) ); + } +#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + + uint32_t mag = (flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT; + uint32_t min = (flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT; + uint32_t mip = (flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT; + GLenum minFilter = s_textureFilterMin[min][1 < numMips ? mip+1 : 0]; + GL_CHECK(glTexParameteri(target, GL_TEXTURE_MAG_FILTER, s_textureFilterMag[mag]) ); + GL_CHECK(glTexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilter) ); + if (0 != (flags & (BGFX_TEXTURE_MIN_ANISOTROPIC|BGFX_TEXTURE_MAG_ANISOTROPIC) ) + && 0.0f < s_renderCtx.m_maxAnisotropy) + { + GL_CHECK(glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, s_renderCtx.m_maxAnisotropy) ); + } + + m_currentFlags = flags; + } + } + + void Texture::commit(uint32_t _stage, uint32_t _flags) + { + GL_CHECK(glActiveTexture(GL_TEXTURE0+_stage) ); + GL_CHECK(glBindTexture(m_target, m_id) ); + +#if BGFX_CONFIG_RENDERER_OPENGLES2 + // GLES2 doesn't have support for sampler object. + setSamplerState(_flags); +#elif BGFX_CONFIG_RENDERER_OPENGL < 31 + // In case that GL 2.1 sampler object is supported via extension. + if (s_renderCtx.m_samplerObjectSupport) + { + s_renderCtx.setSamplerState(_stage, m_numMips, _flags); + } + else + { + setSamplerState(_flags); + } +#else + // Everything else has sampler object. + s_renderCtx.setSamplerState(_stage, m_numMips, _flags); +#endif // BGFX_CONFIG_RENDERER_* + } + void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) { BX_TRACE("Create render target %dx%d 0x%02x", _width, _height, _flags); @@ -2382,6 +2478,11 @@ namespace bgfx || s_extension[Extension::OES_vertex_array_object].m_supported ; + s_renderCtx.m_samplerObjectSupport = !!BGFX_CONFIG_RENDERER_OPENGLES3 + || s_extension[Extension::ARB_sampler_objects].m_supported + ; +s_renderCtx.m_samplerObjectSupport = false; + s_renderCtx.m_programBinarySupport = !!BGFX_CONFIG_RENDERER_OPENGLES3 || s_extension[Extension::ARB_get_program_binary].m_supported || s_extension[Extension::OES_get_program_binary].m_supported @@ -3133,27 +3234,26 @@ namespace bgfx { if (invalidHandle != sampler.m_idx) { - GL_CHECK(glActiveTexture(GL_TEXTURE0+stage) ); switch (sampler.m_flags&BGFX_SAMPLER_TYPE_MASK) { case BGFX_SAMPLER_TEXTURE: { - const Texture& texture = s_renderCtx.m_textures[sampler.m_idx]; - GL_CHECK(glBindTexture(texture.m_target, texture.m_id) ); + Texture& texture = s_renderCtx.m_textures[sampler.m_idx]; + texture.commit(stage, sampler.m_flags); } break; case BGFX_SAMPLER_RENDERTARGET_COLOR: { - const RenderTarget& rt = s_renderCtx.m_renderTargets[sampler.m_idx]; - GL_CHECK(glBindTexture(rt.m_color.m_target, rt.m_color.m_id) ); + RenderTarget& rt = s_renderCtx.m_renderTargets[sampler.m_idx]; + rt.m_color.commit(stage, sampler.m_flags); } break; case BGFX_SAMPLER_RENDERTARGET_DEPTH: { - const RenderTarget& rt = s_renderCtx.m_renderTargets[sampler.m_idx]; - GL_CHECK(glBindTexture(rt.m_depth.m_target, rt.m_depth.m_id) ); + RenderTarget& rt = s_renderCtx.m_renderTargets[sampler.m_idx]; + rt.m_depth.commit(stage, sampler.m_flags); } break; } @@ -3186,7 +3286,7 @@ namespace bgfx currentState.m_indexBuffer = state.m_indexBuffer; baseVertex = state.m_startVertex; - GLuint id = s_renderCtx.m_vaoCache.find(hash); + GLuint id = s_renderCtx.m_vaoStateCache.find(hash); if (UINT32_MAX != id) { currentVao = id; @@ -3194,7 +3294,7 @@ namespace bgfx } else { - id = s_renderCtx.m_vaoCache.add(hash); + id = s_renderCtx.m_vaoStateCache.add(hash); currentVao = id; GL_CHECK(glBindVertexArray(id) ); diff --git a/src/renderer_gl.h b/src/renderer_gl.h index b5078655d..4258ed3d8 100755 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -296,7 +296,7 @@ namespace bgfx class ConstantBuffer; - class VaoCache + class VaoStateCache { public: GLuint add(uint32_t _hash) @@ -358,7 +358,7 @@ namespace bgfx m_vaoSet.insert(_hash); } - void invalidate(VaoCache& _vaoCache) + void invalidate(VaoStateCache& _vaoCache) { for (VaoSet::iterator it = m_vaoSet.begin(), itEnd = m_vaoSet.end(); it != itEnd; ++it) { @@ -372,6 +372,58 @@ namespace bgfx VaoSet m_vaoSet; }; +#if !BGFX_CONFIG_RENDERER_OPENGLES2 + class SamplerStateCache + { + public: + GLuint add(uint32_t _hash) + { + invalidate(_hash); + + GLuint samplerId; + GL_CHECK(glGenSamplers(1, &samplerId) ); + + m_hashMap.insert(stl::make_pair(_hash, samplerId) ); + + return samplerId; + } + + GLuint find(uint32_t _hash) + { + HashMap::iterator it = m_hashMap.find(_hash); + if (it != m_hashMap.end() ) + { + return it->second; + } + + return UINT32_MAX; + } + + void invalidate(uint32_t _hash) + { + HashMap::iterator it = m_hashMap.find(_hash); + if (it != m_hashMap.end() ) + { + GL_CHECK(glDeleteSamplers(1, &it->second) ); + m_hashMap.erase(it); + } + } + + void invalidate() + { + for (HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it) + { + GL_CHECK(glDeleteSamplers(1, &it->second) ); + } + m_hashMap.clear(); + } + + private: + typedef stl::unordered_map HashMap; + HashMap m_hashMap; + }; +#endif // !BGFX_CONFIG_RENDERER_OPENGLES2 + struct IndexBuffer { void create(uint32_t _size, void* _data) @@ -461,6 +513,9 @@ namespace bgfx , m_target(GL_TEXTURE_2D) , m_fmt(GL_ZERO) , m_type(GL_ZERO) + , m_flags(0) + , m_currentFlags(UINT32_MAX) + , m_numMips(0) , m_compressed(false) { } @@ -471,11 +526,16 @@ namespace bgfx void createDepth(uint32_t _width, uint32_t _height); void destroy(); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, const Memory* _mem); + void setSamplerState(uint32_t _flags); + void commit(uint32_t _stage, uint32_t _flags); GLuint m_id; GLenum m_target; GLenum m_fmt; GLenum m_type; + uint32_t m_flags; + uint32_t m_currentFlags; + uint8_t m_numMips; bool m_compressed; };