Exposed renderer capabilities.

This commit is contained in:
bkaradzic 2013-10-10 18:29:57 -07:00
parent 781c9cda5b
commit f440f160f9
19 changed files with 305 additions and 98 deletions

View file

@ -291,7 +291,6 @@ Todo
- DX11: MSAA.
- Fullscreen mode.
- ETC2, PVRTC1/2 decoding fallback for targets that don't support it natively.
- Capabilities flags for user to have idea what features are available.
Contact
-------

View file

@ -113,9 +113,12 @@ int _main_(int /*_argc*/, char** /*_argv*/)
, 0
);
// Get renderer capabilities info.
const bgfx::Caps* caps = bgfx::getCaps();
// Setup root path for binary shaders. Shader binaries are different
// for each renderer.
switch (bgfx::getRendererType() )
switch (caps->rendererType)
{
default:
case bgfx::RendererType::Direct3D9:
@ -195,6 +198,16 @@ int _main_(int /*_argc*/, char** /*_argv*/)
bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Geometry instancing.");
bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
// Check if instancing is supported.
if (0 == (BGFX_CAPS_INSTANCING & caps->supported) )
{
// When instancing is not supported by GPU, implement alternative
// code path that doesn't use instancing.
bool blink = uint32_t(time*3.0f)&1;
bgfx::dbgTextPrintf(0, 5, blink ? 0x1f : 0x01, " Instancing is not supported by GPU. ");
}
else
{
float at[3] = { 0.0f, 0.0f, 0.0f };
float eye[3] = { 0.0f, 0.0f, -35.0f };
@ -249,6 +262,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
// Submit primitive for rendering to view 0.
bgfx::submit(0);
}
}
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.

View file

@ -268,9 +268,14 @@ int _main_(int /*_argc*/, char** /*_argv*/)
, 0
);
// Get renderer capabilities info.
const bgfx::Caps* caps = bgfx::getCaps();
bool instancingSupported = 0 != (caps->supported & BGFX_CAPS_INSTANCING);
// Setup root path for binary shaders. Shader binaries are different
// for each renderer.
switch (bgfx::getRendererType() )
switch (caps->rendererType)
{
default:
case bgfx::RendererType::Direct3D9:
@ -320,7 +325,7 @@ int _main_(int /*_argc*/, char** /*_argv*/)
bgfx::UniformHandle u_lightRgbInnerR = bgfx::createUniform("u_lightRgbInnerR", bgfx::UniformType::Uniform4fv, numLights);
// Load vertex shader.
mem = loadShader("vs_bump");
mem = loadShader(instancingSupported ? "vs_bump_instanced" : "vs_bump");
bgfx::VertexShaderHandle vsh = bgfx::createVertexShader(mem);
// Load fragment shader.
@ -406,6 +411,8 @@ int _main_(int /*_argc*/, char** /*_argv*/)
const uint16_t instanceStride = 64;
const uint16_t numInstances = 3;
if (instancingSupported)
{
// Write instance data for 3x3 cubes.
for (uint32_t yy = 0; yy < 3; ++yy)
{
@ -425,6 +432,9 @@ int _main_(int /*_argc*/, char** /*_argv*/)
data += instanceStride;
}
// Set instance data buffer.
bgfx::setInstanceDataBuffer(idb, numInstances);
// Set vertex and fragment shaders.
bgfx::setProgram(program);
@ -432,9 +442,6 @@ int _main_(int /*_argc*/, char** /*_argv*/)
bgfx::setVertexBuffer(vbh);
bgfx::setIndexBuffer(ibh);
// Set instance data buffer.
bgfx::setInstanceDataBuffer(idb, numInstances);
// Bind textures.
bgfx::setTexture(0, u_texColor, textureColor);
bgfx::setTexture(1, u_texNormal, textureNormal);
@ -452,6 +459,47 @@ int _main_(int /*_argc*/, char** /*_argv*/)
bgfx::submit(0);
}
}
}
else
{
for (uint32_t yy = 0; yy < 3; ++yy)
{
for (uint32_t xx = 0; xx < 3; ++xx)
{
float mtx[16];
mtxRotateXY(mtx, time*0.023f + xx*0.21f, time*0.03f + yy*0.37f);
mtx[12] = -3.0f + float(xx)*3.0f;
mtx[13] = -3.0f + float(yy)*3.0f;
mtx[14] = 0.0f;
// Set transform for draw call.
bgfx::setTransform(mtx);
// Set vertex and fragment shaders.
bgfx::setProgram(program);
// Set vertex and index buffer.
bgfx::setVertexBuffer(vbh);
bgfx::setIndexBuffer(ibh);
// Bind textures.
bgfx::setTexture(0, u_texColor, textureColor);
bgfx::setTexture(1, u_texNormal, textureNormal);
// Set render states.
bgfx::setState(0
|BGFX_STATE_RGB_WRITE
|BGFX_STATE_ALPHA_WRITE
|BGFX_STATE_DEPTH_WRITE
|BGFX_STATE_DEPTH_TEST_LESS
|BGFX_STATE_MSAA
);
// Submit primitive for rendering to view 0.
bgfx::submit(0);
}
}
}
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.

View file

@ -1,4 +1,4 @@
$input a_position, a_normal, a_tangent, a_texcoord0, i_data0, i_data1, i_data2, i_data3
$input a_position, a_normal, a_tangent, a_texcoord0
$output v_wpos, v_view, v_normal, v_tangent, v_bitangent, v_texcoord0
/*
@ -10,20 +10,14 @@ $output v_wpos, v_view, v_normal, v_tangent, v_bitangent, v_texcoord0
void main()
{
mat4 model;
model[0] = i_data0;
model[1] = i_data1;
model[2] = i_data2;
model[3] = i_data3;
vec3 wpos = instMul(model, vec4(a_position, 1.0) ).xyz;
vec3 wpos = mul(u_model[0], vec4(a_position, 1.0) ).xyz;
gl_Position = mul(u_viewProj, vec4(wpos, 1.0) );
vec4 normal = a_normal * 2.0f - 1.0f;
vec3 wnormal = instMul(model, vec4(normal.xyz, 0.0) ).xyz;
vec3 wnormal = mul(u_model[0], vec4(normal.xyz, 0.0) ).xyz;
vec4 tangent = a_tangent * 2.0f - 1.0f;
vec3 wtangent = instMul(model, vec4(tangent.xyz, 0.0) ).xyz;
vec3 wtangent = mul(u_model[0], vec4(tangent.xyz, 0.0) ).xyz;
vec3 viewNormal = normalize(mul(u_view, vec4(wnormal, 0.0) ).xyz);
vec3 viewTangent = normalize(mul(u_view, vec4(wtangent, 0.0) ).xyz);
@ -33,7 +27,7 @@ void main()
v_wpos = wpos;
vec3 view = mul(u_view, vec4(wpos, 0.0) ).xyz;
v_view = instMul(view, tbn);
v_view = mul(view, tbn);
v_normal = viewNormal;
v_tangent = viewTangent;

View file

@ -0,0 +1,43 @@
$input a_position, a_normal, a_tangent, a_texcoord0, i_data0, i_data1, i_data2, i_data3
$output v_wpos, v_view, v_normal, v_tangent, v_bitangent, v_texcoord0
/*
* Copyright 2011-2013 Branimir Karadzic. All rights reserved.
* License: http://www.opensource.org/licenses/BSD-2-Clause
*/
#include "../common/common.sh"
void main()
{
mat4 model;
model[0] = i_data0;
model[1] = i_data1;
model[2] = i_data2;
model[3] = i_data3;
vec3 wpos = instMul(model, vec4(a_position, 1.0) ).xyz;
gl_Position = mul(u_viewProj, vec4(wpos, 1.0) );
vec4 normal = a_normal * 2.0f - 1.0f;
vec3 wnormal = instMul(model, vec4(normal.xyz, 0.0) ).xyz;
vec4 tangent = a_tangent * 2.0f - 1.0f;
vec3 wtangent = instMul(model, vec4(tangent.xyz, 0.0) ).xyz;
vec3 viewNormal = normalize(mul(u_view, vec4(wnormal, 0.0) ).xyz);
vec3 viewTangent = normalize(mul(u_view, vec4(wtangent, 0.0) ).xyz);
vec3 viewBitangent = cross(viewNormal, viewTangent) * tangent.w;
mat3 tbn = mat3(viewTangent, viewBitangent, viewNormal);
v_wpos = wpos;
vec3 view = mul(u_view, vec4(wpos, 0.0) ).xyz;
v_view = instMul(view, tbn);
v_normal = viewNormal;
v_tangent = viewTangent;
v_bitangent = viewBitangent;
v_texcoord0 = a_texcoord0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -226,6 +226,25 @@
#define BGFX_RESET_VSYNC UINT32_C(0x00000080)
#define BGFX_RESET_CAPTURE UINT32_C(0x00000100)
///
#define BGFX_CAPS_TEXTURE_FORMAT_BC1 UINT64_C(0x0000000000000001)
#define BGFX_CAPS_TEXTURE_FORMAT_BC2 UINT64_C(0x0000000000000002)
#define BGFX_CAPS_TEXTURE_FORMAT_BC3 UINT64_C(0x0000000000000004)
#define BGFX_CAPS_TEXTURE_FORMAT_BC4 UINT64_C(0x0000000000000008)
#define BGFX_CAPS_TEXTURE_FORMAT_BC5 UINT64_C(0x0000000000000010)
#define BGFX_CAPS_TEXTURE_FORMAT_ETC1 UINT64_C(0x0000000000000020)
#define BGFX_CAPS_TEXTURE_FORMAT_ETC2 UINT64_C(0x0000000000000040)
#define BGFX_CAPS_TEXTURE_FORMAT_ETC2A UINT64_C(0x0000000000000080)
#define BGFX_CAPS_TEXTURE_FORMAT_ETC2A1 UINT64_C(0x0000000000000100)
#define BGFX_CAPS_TEXTURE_FORMAT_PTC12 UINT64_C(0x0000000000000200)
#define BGFX_CAPS_TEXTURE_FORMAT_PTC14 UINT64_C(0x0000000000000400)
#define BGFX_CAPS_TEXTURE_FORMAT_PTC14A UINT64_C(0x0000000000000800)
#define BGFX_CAPS_TEXTURE_FORMAT_PTC12A UINT64_C(0x0000000000001000)
#define BGFX_CAPS_TEXTURE_FORMAT_PTC22 UINT64_C(0x0000000000002000)
#define BGFX_CAPS_TEXTURE_FORMAT_PTC24 UINT64_C(0x0000000000004000)
#define BGFX_CAPS_TEXTURE_3D UINT64_C(0x0000000000010000)
#define BGFX_CAPS_INSTANCING UINT64_C(0x0000000000020000)
///
#define BGFX_HANDLE(_name) \
struct _name { uint16_t idx; }; \
@ -419,6 +438,26 @@ namespace bgfx
uint32_t size;
};
/// Renderer capabilities.
struct Caps
{
/// Renderer backend type.
RendererType::Enum rendererType;
/// Supported functionality, it includes emulated functionality.
/// Checking supported and not emulated will give functionality
/// natively supported by renderer.
uint64_t supported;
/// Emulated functionality. For example some texture compression
/// modes are not natively supported by all renderers. The library
/// internally decompresses texture into supported format.
uint64_t emulated;
/// Maximum texture size.
uint16_t maxTextureSize;
};
struct TransientIndexBuffer
{
uint8_t* data;
@ -568,6 +607,9 @@ namespace bgfx
/// singlethreaded renderer this call does frame rendering.
void frame();
/// Returns renderer capabilities.
const Caps* getCaps();
/// Allocate buffer to pass to bgfx calls. Data will be freed inside bgfx.
const Memory* alloc(uint32_t _size);

View file

@ -10,7 +10,9 @@ namespace bgfx
#define BGFX_MAIN_THREAD_MAGIC 0x78666762
#if BGFX_CONFIG_MULTITHREADED && !BX_PLATFORM_OSX && !BX_PLATFORM_IOS
# define BGFX_CHECK_MAIN_THREAD() BX_CHECK(BGFX_MAIN_THREAD_MAGIC == s_threadIndex, "Must be called from main thread.")
# define BGFX_CHECK_MAIN_THREAD() \
BX_CHECK(NULL != s_ctx, "Library is not initialized yet."); \
BX_CHECK(BGFX_MAIN_THREAD_MAGIC == s_threadIndex, "Must be called from main thread.")
# define BGFX_CHECK_RENDER_THREAD() BX_CHECK(BGFX_MAIN_THREAD_MAGIC != s_threadIndex, "Must be called from render thread.")
#else
# define BGFX_CHECK_MAIN_THREAD()
@ -189,6 +191,8 @@ namespace bgfx
CallbackI* g_callback = NULL;
bx::ReallocatorI* g_allocator = NULL;
Caps g_caps;
static BX_THREAD uint32_t s_threadIndex = 0;
static Context* s_ctx = NULL;
@ -619,6 +623,12 @@ namespace bgfx
bx::radixSort64(m_sortKeys, s_ctx->m_tempKeys, m_sortValues, s_ctx->m_tempValues, m_num);
}
const Caps* getCaps()
{
BGFX_CHECK_MAIN_THREAD();
return &g_caps;
}
RendererType::Enum getRendererType()
{
#if BGFX_CONFIG_RENDERER_DIRECT3D9
@ -640,6 +650,20 @@ namespace bgfx
{
BX_TRACE("Init...");
memset(&g_caps, 0, sizeof(g_caps) );
g_caps.rendererType = getRendererType();
g_caps.emulated = 0
| BGFX_CAPS_TEXTURE_FORMAT_BC1
| BGFX_CAPS_TEXTURE_FORMAT_BC2
| BGFX_CAPS_TEXTURE_FORMAT_BC3
| BGFX_CAPS_TEXTURE_FORMAT_BC4
| BGFX_CAPS_TEXTURE_FORMAT_BC5
| BGFX_CAPS_TEXTURE_FORMAT_ETC1
| BGFX_CAPS_TEXTURE_FORMAT_ETC2
| BGFX_CAPS_TEXTURE_FORMAT_ETC2A
| BGFX_CAPS_TEXTURE_FORMAT_ETC2A1
;
if (NULL != _allocator)
{
g_allocator = _allocator;
@ -1696,6 +1720,7 @@ namespace bgfx
const InstanceDataBuffer* allocInstanceDataBuffer(uint32_t _num, uint16_t _stride)
{
BGFX_CHECK_MAIN_THREAD();
BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_INSTANCING), "Instancing is not supported! Use bgfx::getCaps to check backend renderer capabilities.");
BX_CHECK(0 < _num, "Requesting 0 instanced data vertices.");
return s_ctx->allocInstanceDataBuffer(_num, _stride);
}
@ -1823,6 +1848,7 @@ namespace bgfx
TextureHandle createTexture3D(uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
{
BGFX_CHECK_MAIN_THREAD();
BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_TEXTURE_3D), "Texture3D is not supported! Use bgfx::getCaps to check backend renderer capabilities.");
#if BGFX_CONFIG_DEBUG
if (NULL != _mem)

View file

@ -227,6 +227,7 @@ namespace bgfx
extern const uint32_t g_uniformTypeSize[UniformType::Count+1];
extern CallbackI* g_callback;
extern bx::ReallocatorI* g_allocator;
extern Caps g_caps;
void release(const Memory* _mem);
const char* getAttribName(Attrib::Enum _attr);

View file

@ -478,6 +478,18 @@ namespace bgfx
m_uniformReg.add(getPredefinedUniformName(PredefinedUniform::Enum(ii) ), &m_predefinedUniforms[ii]);
}
g_caps.emulated &= ~( 0
| BGFX_CAPS_TEXTURE_FORMAT_BC1
| BGFX_CAPS_TEXTURE_FORMAT_BC2
| BGFX_CAPS_TEXTURE_FORMAT_BC3
| BGFX_CAPS_TEXTURE_FORMAT_BC4
);
g_caps.supported |= ( 0
| BGFX_CAPS_INSTANCING
| BGFX_CAPS_TEXTURE_3D
);
g_caps.maxTextureSize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
postReset();
}

View file

@ -409,6 +409,14 @@ namespace bgfx
BX_TRACE("Max fragment shader 2.0 instr. slots: %d", m_caps.PS20Caps.NumInstructionSlots);
BX_TRACE("Max fragment shader 3.0 instr. slots: %d", m_caps.MaxPixelShader30InstructionSlots);
g_caps.emulated &= ~( 0
| BGFX_CAPS_TEXTURE_FORMAT_BC1
| BGFX_CAPS_TEXTURE_FORMAT_BC2
| BGFX_CAPS_TEXTURE_FORMAT_BC3
);
g_caps.supported |= BGFX_CAPS_TEXTURE_3D;
g_caps.maxTextureSize = bx::uint32_min(m_caps.MaxTextureWidth, m_caps.MaxTextureHeight);
#if BGFX_CONFIG_RENDERER_USE_EXTENSIONS
BX_TRACE("Extended formats:");
for (uint32_t ii = 0; ii < ExtendedFormat::Count; ++ii)
@ -434,6 +442,12 @@ namespace bgfx
s_textureFormat[TextureFormat::BC4].m_fmt = s_extendedFormats[ExtendedFormat::Ati1].m_supported ? D3DFMT_ATI1 : D3DFMT_UNKNOWN;
s_textureFormat[TextureFormat::BC5].m_fmt = s_extendedFormats[ExtendedFormat::Ati2].m_supported ? D3DFMT_ATI2 : D3DFMT_UNKNOWN;
g_caps.emulated &= ~( 0
| (D3DFMT_UNKNOWN != s_textureFormat[TextureFormat::BC4].m_fmt ? BGFX_CAPS_TEXTURE_FORMAT_BC4 : 0)
| (D3DFMT_UNKNOWN != s_textureFormat[TextureFormat::BC5].m_fmt ? BGFX_CAPS_TEXTURE_FORMAT_BC5 : 0)
);
g_caps.supported |= m_instancing ? BGFX_CAPS_INSTANCING : 0;
#endif // BGFX_CONFIG_RENDERER_USE_EXTENSIONS
uint32_t index = 1;

View file

@ -2210,8 +2210,7 @@ namespace bgfx
glGetIntegerv(_pname, &result);
GLenum err = glGetError();
BX_WARN(0 == err, "glGetIntegerv(0x%04x, ...) failed with GL error: 0x%04x.", _pname, err);
BX_UNUSED(err);
return result;
return 0 == err ? result : 0;
}
void Context::rendererInit()
@ -2370,7 +2369,8 @@ namespace bgfx
s_textureFormat[TextureFormat::BC4].m_supported = bc45Supported;
s_textureFormat[TextureFormat::BC5].m_supported = bc45Supported;
s_textureFormat[TextureFormat::ETC1].m_supported = s_extension[Extension::OES_compressed_ETC1_RGB8_texture].m_supported;
bool etc1Supported = s_extension[Extension::OES_compressed_ETC1_RGB8_texture].m_supported;
s_textureFormat[TextureFormat::ETC1].m_supported = etc1Supported;
bool etc2Supported = !!BGFX_CONFIG_RENDERER_OPENGLES3
|| s_extension[Extension::ARB_ES3_compatibility].m_supported
@ -2398,6 +2398,17 @@ namespace bgfx
s_textureFormat[TextureFormat::PTC22].m_supported = ptc2Supported;
s_textureFormat[TextureFormat::PTC24].m_supported = ptc2Supported;
g_caps.emulated &= ~( 0
| bc123Supported ? BGFX_CAPS_TEXTURE_FORMAT_BC1|BGFX_CAPS_TEXTURE_FORMAT_BC2|BGFX_CAPS_TEXTURE_FORMAT_BC3 : 0
| bc45Supported ? BGFX_CAPS_TEXTURE_FORMAT_BC4|BGFX_CAPS_TEXTURE_FORMAT_BC5 : 0
| etc1Supported ? BGFX_CAPS_TEXTURE_FORMAT_ETC1 : 0
| etc2Supported ? BGFX_CAPS_TEXTURE_FORMAT_ETC2|BGFX_CAPS_TEXTURE_FORMAT_ETC2A|BGFX_CAPS_TEXTURE_FORMAT_ETC2A1 : 0
| ptc1Supported ? BGFX_CAPS_TEXTURE_FORMAT_PTC12|BGFX_CAPS_TEXTURE_FORMAT_PTC14|BGFX_CAPS_TEXTURE_FORMAT_PTC14A|BGFX_CAPS_TEXTURE_FORMAT_PTC12A : 0
| ptc2Supported ? BGFX_CAPS_TEXTURE_FORMAT_PTC22|BGFX_CAPS_TEXTURE_FORMAT_PTC24 : 0
);
g_caps.supported |= !!(BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3) ? BGFX_CAPS_TEXTURE_3D : 0;
g_caps.maxTextureSize = glGet(GL_MAX_TEXTURE_SIZE);
s_renderCtx->m_vaoSupport = !!BGFX_CONFIG_RENDERER_OPENGLES3
|| s_extension[Extension::ARB_vertex_array_object].m_supported
|| s_extension[Extension::OES_vertex_array_object].m_supported
@ -2485,7 +2496,9 @@ namespace bgfx
s_textureFormat[TextureFormat::BC5].m_internalFmt = GL_COMPRESSED_RED_GREEN_RGTC2_EXT;
}
#if !BGFX_CONFIG_RENDERER_OPENGLES3
#if BGFX_CONFIG_RENDERER_OPENGLES3
g_caps.supported |= BGFX_CAPS_INSTANCING;
#else
s_vertexAttribDivisor = stubVertexAttribDivisor;
s_drawArraysInstanced = stubDrawArraysInstanced;
s_drawElementsInstanced = stubDrawElementsInstanced;
@ -2501,6 +2514,7 @@ namespace bgfx
s_vertexAttribDivisor = glVertexAttribDivisor;
s_drawArraysInstanced = glDrawArraysInstanced;
s_drawElementsInstanced = glDrawElementsInstanced;
g_caps.supported |= BGFX_CAPS_INSTANCING;
}
}
# endif // !BX_PLATFORM_IOS