Added ability to change sampler filter when setting texture. GL/GLES3: Added support for GL_ARB_sampler_objects.

This commit is contained in:
bkaradzic 2013-07-24 21:59:59 -07:00
parent 84eec31043
commit a1dfd1ab0d
11 changed files with 557 additions and 366 deletions

View File

@ -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

View File

@ -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.
///

View File

@ -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)

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}
}

View File

@ -15,6 +15,8 @@
namespace bgfx
{
typedef HRESULT (WINAPI * PFN_CREATEDXGIFACTORY)(REFIID _riid, void** _factory);
template <typename Ty>
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;

View File

@ -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:

View File

@ -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;
};

View File

@ -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) );

View File

@ -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<uint32_t, GLuint> 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;
};