Added initial occlusion query support.

This commit is contained in:
Branimir Karadžić 2015-11-01 17:28:23 -08:00
parent 2cb5299588
commit 6aa9629816
17 changed files with 782 additions and 119 deletions

View File

@ -9,11 +9,7 @@
#include "common.h"
#include "bgfx_utils.h"
#include <bgfx/bgfx.h>
#include <bx/timer.h>
#include <bx/readerwriter.h>
#include <bx/fpumath.h>
#include "entry/entry.h"
#include "camera.h"
#include "imgui/imgui.h"
@ -1002,7 +998,7 @@ int _main_(int _argc, char** _argv)
last = now;
const double freq = double(bx::getHPFrequency() );
const double toMs = 1000.0/freq;
float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) );
const float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) );
const float deltaTime = float(frameTime/freq);
s_uniforms.m_time = time;

View File

@ -0,0 +1,272 @@
/*
* Copyright 2011-2015 Branimir Karadzic. All rights reserved.
* License: http://www.opensource.org/licenses/BSD-2-Clause
*/
#include "common.h"
#include "bgfx_utils.h"
#include "camera.h"
#define CUBES_DIM 10
struct PosColorVertex
{
float m_x;
float m_y;
float m_z;
uint32_t m_abgr;
static void init()
{
ms_decl
.begin()
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
.end();
};
static bgfx::VertexDecl ms_decl;
};
bgfx::VertexDecl PosColorVertex::ms_decl;
static PosColorVertex s_cubeVertices[8] =
{
{-1.0f, 1.0f, 1.0f, 0xff000000 },
{ 1.0f, 1.0f, 1.0f, 0xff0000ff },
{-1.0f, -1.0f, 1.0f, 0xff00ff00 },
{ 1.0f, -1.0f, 1.0f, 0xff00ffff },
{-1.0f, 1.0f, -1.0f, 0xffff0000 },
{ 1.0f, 1.0f, -1.0f, 0xffff00ff },
{-1.0f, -1.0f, -1.0f, 0xffffff00 },
{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};
static const uint16_t s_cubeIndices[36] =
{
0, 1, 2, // 0
1, 3, 2,
4, 6, 5, // 2
5, 6, 7,
0, 2, 4, // 4
4, 2, 6,
1, 5, 3, // 6
5, 7, 3,
0, 4, 1, // 8
4, 5, 1,
2, 3, 6, // 10
6, 3, 7,
};
class Occlusion : public entry::AppI
{
void init(int _argc, char** _argv) BX_OVERRIDE
{
Args args(_argc, _argv);
m_state.m_width = 1280;
m_state.m_height = 720;
m_debug = BGFX_DEBUG_TEXT;
m_reset = BGFX_RESET_VSYNC;
bgfx::init(args.m_type, args.m_pciId);
bgfx::reset(m_state.m_width, m_state.m_height, m_reset);
// Enable debug text.
bgfx::setDebug(m_debug);
// Set view 0 clear state.
bgfx::setViewClear(0
, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
, 0x303030ff
, 1.0f
, 0
);
bgfx::setViewClear(2
, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
, 0x202020ff
, 1.0f
, 0
);
// Create vertex stream declaration.
PosColorVertex::init();
// Create static vertex buffer.
m_vbh = bgfx::createVertexBuffer(
// Static data can be passed with bgfx::makeRef
bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
, PosColorVertex::ms_decl
);
// Create static index buffer.
m_ibh = bgfx::createIndexBuffer(
// Static data can be passed with bgfx::makeRef
bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) )
);
// Create program from shaders.
m_program = loadProgram("vs_cubes", "fs_cubes");
for (uint32_t ii = 0; ii < BX_COUNTOF(m_occlusionQueries); ++ii)
{
m_occlusionQueries[ii] = bgfx::createOcclusionQuery();
}
cameraCreate();
const float initialPos[3] = { 15.5f, 0.0f, -15.5f };
cameraSetPosition(initialPos);
cameraSetHorizontalAngle(bx::toRad(-45.0f) );
m_timeOffset = bx::getHPCounter();
}
virtual int shutdown() BX_OVERRIDE
{
// Cleanup.
cameraDestroy();
for (uint32_t ii = 0; ii < BX_COUNTOF(m_occlusionQueries); ++ii)
{
bgfx::destroyOcclusionQuery(m_occlusionQueries[ii]);
}
bgfx::destroyIndexBuffer(m_ibh);
bgfx::destroyVertexBuffer(m_vbh);
bgfx::destroyProgram(m_program);
// Shutdown bgfx.
bgfx::shutdown();
return 0;
}
bool update() BX_OVERRIDE
{
if (!entry::processWindowEvents(m_state, m_debug, m_reset) )
{
int64_t now = bx::getHPCounter();
static int64_t last = now;
const int64_t frameTime = now - last;
last = now;
const double freq = double(bx::getHPFrequency() );
const double toMs = 1000.0/freq;
const float time = (float)( (now-m_timeOffset)/double(bx::getHPFrequency() ) );
const float deltaTime = float(frameTime/freq);
// Use debug font to print information about this example.
bgfx::dbgTextClear();
bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/26-occlusion");
bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Using occlusion query to do conditional rendering.");
bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
uint32_t width = m_state.m_width;
uint32_t height = m_state.m_height;
// Update camera.
float view[16];
cameraUpdate(deltaTime, m_state.m_mouse);
cameraGetViewMtx(view);
// Set view and projection matrix for view 0.
const bgfx::HMD* hmd = bgfx::getHMD();
if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) )
{
float viewHead[16];
float eye[3] = {};
bx::mtxQuatTranslationHMD(viewHead, hmd->eye[0].rotation, eye);
float tmp[16];
bx::mtxMul(tmp, view, viewHead);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 10000.0f);
bgfx::setViewTransform(0, tmp, proj);
bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height);
bgfx::setViewTransform(1, tmp, proj);
bgfx::setViewRect(1, 0, 0, hmd->width, hmd->height);
}
else
{
float proj[16];
bx::mtxProj(proj, 90.0f, float(width)/float(height), 0.1f, 10000.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewRect(0, 0, 0, width, height);
bgfx::setViewTransform(1, view, proj);
bgfx::setViewRect(1, 0, 0, width, height);
float at[3] = { 0.0f, 0.0f, 0.0f };
float eye[3] = { 17.5f, 10.0f, -17.5f };
bx::mtxLookAt(view, eye, at);
bgfx::setViewTransform(2, view, proj);
bgfx::setViewRect(2, 10, height - height/4 - 10, width/4, height/4);
}
for (uint32_t yy = 0; yy < CUBES_DIM; ++yy)
{
for (uint32_t xx = 0; xx < CUBES_DIM; ++xx)
{
float mtx[16];
bx::mtxRotateXY(mtx, time + xx*0.21f, time + yy*0.37f);
mtx[12] = -(CUBES_DIM-1) * 3.0f / 2.0f + float(xx)*3.0f;
mtx[13] = 0.0f;
mtx[14] = -(CUBES_DIM-1) * 3.0f / 2.0f + float(yy)*3.0f;
bgfx::OcclusionQueryHandle occlusionQuery = m_occlusionQueries[yy*CUBES_DIM+xx];
bgfx::setTransform(mtx);
bgfx::setVertexBuffer(m_vbh);
bgfx::setIndexBuffer(m_ibh);
bgfx::setCondition(occlusionQuery, true);
bgfx::setState(BGFX_STATE_DEFAULT);
bgfx::submit(0, m_program);
bgfx::setTransform(mtx);
bgfx::setVertexBuffer(m_vbh);
bgfx::setIndexBuffer(m_ibh);
bgfx::setState(0
| BGFX_STATE_DEPTH_TEST_LEQUAL
| BGFX_STATE_CULL_CW
);
bgfx::submit(1, m_program, occlusionQuery);
bgfx::setTransform(mtx);
bgfx::setVertexBuffer(m_vbh);
bgfx::setIndexBuffer(m_ibh);
bgfx::setCondition(occlusionQuery, true);
bgfx::setState(BGFX_STATE_DEFAULT);
bgfx::submit(2, m_program);
}
}
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
bgfx::frame();
return true;
}
return false;
}
uint32_t m_reset;
uint32_t m_debug;
bgfx::VertexBufferHandle m_vbh;
bgfx::IndexBufferHandle m_ibh;
bgfx::ProgramHandle m_program;
int64_t m_timeOffset;
bgfx::OcclusionQueryHandle m_occlusionQueries[CUBES_DIM*CUBES_DIM];
entry::WindowState m_state;
};
ENTRY_IMPLEMENT_MAIN(Occlusion);

View File

@ -6,8 +6,10 @@
#include <bx/timer.h>
#include <bx/fpumath.h>
#include "camera.h"
#include "entry/entry.h"
#include "entry/cmd.h"
#include "entry/input.h"
#include <bx/allocator.h>
int cmdMove(CmdContext* /*_context*/, void* /*_userData*/, int _argc, char const* const* _argv)
{
@ -63,7 +65,9 @@ static const InputBinding s_camBindings[] =
{ entry::Key::GamepadDown, entry::Modifier::None, 0, cmd, "move backward" },
{ entry::Key::KeyD, entry::Modifier::None, 0, cmd, "move right" },
{ entry::Key::GamepadRight, entry::Modifier::None, 0, cmd, "move right" },
{ entry::Key::KeyQ, entry::Modifier::None, 0, cmd, "move down" },
{ entry::Key::GamepadShoulderL, entry::Modifier::None, 0, cmd, "move down" },
{ entry::Key::KeyE, entry::Modifier::None, 0, cmd, "move up" },
{ entry::Key::GamepadShoulderR, entry::Modifier::None, 0, cmd, "move up" },
INPUT_BINDING_END
@ -294,12 +298,12 @@ static Camera* s_camera = NULL;
void cameraCreate()
{
s_camera = new Camera;
s_camera = BX_NEW(entry::getAllocator(), Camera);
}
void cameraDestroy()
{
delete s_camera;
BX_DELETE(entry::getAllocator(), s_camera);
s_camera = NULL;
}

View File

@ -27,6 +27,8 @@ rebuild:
@make -s --no-print-directory rebuild -C 21-deferred
@make -s --no-print-directory rebuild -C 23-vectordisplay
@make -s --no-print-directory rebuild -C 24-nbody
# @make -s --no-print-directory rebuild -C 25-c99
# @make -s --no-print-directory rebuild -C 26-occlusion
@make -s --no-print-directory rebuild -C common/font
@make -s --no-print-directory rebuild -C common/imgui
@make -s --no-print-directory rebuild -C common/nanovg

View File

@ -282,6 +282,7 @@ namespace bgfx
BGFX_HANDLE(FrameBufferHandle);
BGFX_HANDLE(IndexBufferHandle);
BGFX_HANDLE(IndirectBufferHandle);
BGFX_HANDLE(OcclusionQueryHandle);
BGFX_HANDLE(ProgramHandle);
BGFX_HANDLE(ShaderHandle);
BGFX_HANDLE(TextureHandle);
@ -1529,6 +1530,12 @@ namespace bgfx
///
void destroyUniform(UniformHandle _handle);
///
OcclusionQueryHandle createOcclusionQuery();
///
void destroyOcclusionQuery(OcclusionQueryHandle _handle);
/// Set palette color value.
///
/// @param[in] _index Index into palette.
@ -1729,6 +1736,15 @@ namespace bgfx
///
void setState(uint64_t _state, uint32_t _rgba = 0);
/// Set condition for rendering.
///
/// @param[in] _handle Occlusion query handle.
/// @param[in] _visible Render if occlusion query is visible.
///
/// @attention C99 equivalent is `bgfx_set_condition`.
///
void setCondition(OcclusionQueryHandle _handle, bool _visible);
/// Set stencil test state.
///
/// @param[in] _fstencil Front stencil state.
@ -1946,19 +1962,31 @@ namespace bgfx
/// Submit primitive for rendering.
///
/// @param[in] _id View id.
/// @param[in] _handle Program.
/// @param[in] _program Program.
/// @param[in] _depth Depth for sorting.
/// @returns Number of draw calls.
///
/// @attention C99 equivalent is `bgfx_submit`.
///
uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth = 0);
uint32_t submit(uint8_t _id, ProgramHandle _program, int32_t _depth = 0);
/// Submit primitive with occlusion query for rendering.
///
/// @param[in] _id View id.
/// @param[in] _program Program.
/// @param[in] _occlusionQuery Occlusion query.
/// @param[in] _depth Depth for sorting.
/// @returns Number of draw calls.
///
/// @attention C99 equivalent is `bgfx_submit_occlusion_query.
///
uint32_t submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth = 0);
/// Submit primitive for rendering with index and instance data info from
/// indirect buffer.
///
/// @param[in] _id View id.
/// @param[in] _handle Program.
/// @param[in] _program Program.
/// @param[in] _indirectHandle Indirect buffer.
/// @param[in] _start First element in indirect buffer.
/// @param[in] _num Number of dispatches.
@ -1966,7 +1994,7 @@ namespace bgfx
///
/// @attention C99 equivalent is `bgfx_submit_indirect`.
///
uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start = 0, uint16_t _num = 1, int32_t _depth = 0);
uint32_t submit(uint8_t _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start = 0, uint16_t _num = 1, int32_t _depth = 0);
/// Set compute index buffer.
///

View File

@ -71,7 +71,9 @@
/// MSAA frame buffer.
#define BGFX_STATE_MSAA UINT64_C(0x1000000000000000) //!< Enable MSAA rasterization.
#define BGFX_STATE_RESERVED_MASK UINT64_C(0xe000000000000000) //!< Internal bits, do not use!
/// Do not use!
#define BGFX_STATE_RESERVED_SHIFT 61 //!< Internal bits shift.
#define BGFX_STATE_RESERVED_MASK UINT64_C(0xe000000000000000) //!< Internal bits mask.
/// See BGFX_STATE_POINT_SIZE(_size) helper macro.
#define BGFX_STATE_NONE UINT64_C(0x0000000000000000) //!< No state.
@ -370,6 +372,7 @@
#define BGFX_CAPS_HIDPI UINT64_C(0x0000000000008000) //!< HiDPI rendering is supported.
#define BGFX_CAPS_TEXTURE_BLIT UINT64_C(0x0000000000010000) //!< Texture blit is supported.
#define BGFX_CAPS_TEXTURE_READ_BACK UINT64_C(0x0000000000020000) //!< Read-back texture is supported.
#define BGFX_CAPS_OCCLUSION_QUERY UINT64_C(0x0000000000040000) //!< Occlusion query is supported.
///
#define BGFX_CAPS_FORMAT_TEXTURE_NONE UINT16_C(0x0000) //!< Texture format is not supported.

View File

@ -192,6 +192,7 @@ BGFX_HANDLE_T(bgfx_dynamic_index_buffer_handle);
BGFX_HANDLE_T(bgfx_dynamic_vertex_buffer_handle);
BGFX_HANDLE_T(bgfx_frame_buffer_handle);
BGFX_HANDLE_T(bgfx_index_buffer_handle);
BGFX_HANDLE_T(bgfx_occlusion_query_handle);
BGFX_HANDLE_T(bgfx_program_handle);
BGFX_HANDLE_T(bgfx_shader_handle);
BGFX_HANDLE_T(bgfx_texture_handle);
@ -677,6 +678,9 @@ BGFX_C_API void bgfx_set_marker(const char* _marker);
/**/
BGFX_C_API void bgfx_set_state(uint64_t _state, uint32_t _rgba);
/**/
BGFX_C_API void bgfx_set_condition(bgfx_occlusion_query_handle_t _handle, bool _visible);
/**/
BGFX_C_API void bgfx_set_stencil(uint32_t _fstencil, uint32_t _bstencil);
@ -737,6 +741,9 @@ BGFX_C_API uint32_t bgfx_touch(uint8_t _id);
/**/
BGFX_C_API uint32_t bgfx_submit(uint8_t _id, bgfx_program_handle_t _handle, int32_t _depth);
/**/
BGFX_C_API uint32_t bgfx_submit_occlusion_query(uint8_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, int32_t _depth);
/**/
BGFX_C_API uint32_t bgfx_submit_indirect(uint8_t _id, bgfx_program_handle_t _handle, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth);

View File

@ -381,6 +381,7 @@ exampleProject("21-deferred")
exampleProject("22-windows")
exampleProject("23-vectordisplay")
exampleProject("24-nbody")
exampleProject("26-occlusion")
-- C99 source doesn't compile under WinRT settings
if not premake.vstudio.iswinrt() then

View File

@ -762,7 +762,7 @@ namespace bgfx
return PredefinedUniform::Count;
}
uint32_t Frame::submit(uint8_t _id, ProgramHandle _handle, int32_t _depth)
uint32_t Frame::submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth)
{
if (m_discard)
{
@ -779,9 +779,9 @@ namespace bgfx
m_uniformEnd = m_uniformBuffer->getPos();
m_key.m_program = invalidHandle == _handle.idx
m_key.m_program = invalidHandle == _program.idx
? 0
: _handle.idx
: _program.idx
;
m_key.m_depth = (uint32_t)_depth;
@ -796,13 +796,22 @@ namespace bgfx
m_draw.m_constBegin = m_uniformBegin;
m_draw.m_constEnd = m_uniformEnd;
m_draw.m_flags |= m_flags;
m_draw.m_stateFlags |= m_stateFlags;
if (isValid(_occlusionQuery) )
{
BX_CHECK(!isValid(m_draw.m_occlusionQuery), "");
m_draw.m_stateFlags |= BGFX_STATE_INTERNAL_OCCLUSION_QUERY;
m_draw.m_occlusionQuery = _occlusionQuery;
}
m_renderItem[m_numRenderItems].draw = m_draw;
++m_numRenderItems;
m_draw.clear();
m_uniformBegin = m_uniformEnd;
m_flags = BGFX_STATE_NONE;
m_stateFlags = BGFX_STATE_NONE;
return m_num;
}
@ -979,6 +988,7 @@ namespace bgfx
CAPS_FLAGS(BGFX_CAPS_HIDPI),
CAPS_FLAGS(BGFX_CAPS_TEXTURE_BLIT),
CAPS_FLAGS(BGFX_CAPS_TEXTURE_READ_BACK),
CAPS_FLAGS(BGFX_CAPS_OCCLUSION_QUERY),
#undef CAPS_FLAGS
};
@ -1331,7 +1341,7 @@ namespace bgfx
{
freeDynamicBuffers();
m_submit->m_resolution = m_resolution;
m_resolution.m_flags &= ~BGFX_RESET_FORCE;
m_resolution.m_flags &= ~BGFX_RESET_INTERNAL_FORCE;
m_submit->m_debug = m_debug;
memcpy(m_submit->m_viewRemap, m_viewRemap, sizeof(m_viewRemap) );
@ -2608,7 +2618,9 @@ again:
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 != (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);
}
@ -2905,6 +2917,7 @@ again:
BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_TEXTURE_3D)
, "Texture3D is not supported! Use bgfx::getCaps to check BGFX_CAPS_TEXTURE_3D backend renderer capabilities."
);
if (_width == 0
|| _height == 0
|| _depth == 0)
@ -3004,6 +3017,24 @@ again:
s_ctx->destroyUniform(_handle);
}
OcclusionQueryHandle createOcclusionQuery()
{
BGFX_CHECK_MAIN_THREAD();
BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_OCCLUSION_QUERY)
, "Occlusion query is not supported, use bgfx::getCaps to test BGFX_CAPS_OCCLUSION_QUERY feature availability"
);
return s_ctx->createOcclusionQuery();
}
void destroyOcclusionQuery(OcclusionQueryHandle _handle)
{
BGFX_CHECK_MAIN_THREAD();
BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_OCCLUSION_QUERY)
, "Occlusion query is not supported, use bgfx::getCaps to test BGFX_CAPS_OCCLUSION_QUERY feature availability"
);
s_ctx->destroyOcclusionQuery(_handle);
}
void setPaletteColor(uint8_t _index, uint32_t _rgba)
{
BGFX_CHECK_MAIN_THREAD();
@ -3133,9 +3164,19 @@ again:
void setState(uint64_t _state, uint32_t _rgba)
{
BGFX_CHECK_MAIN_THREAD();
BX_CHECK(0 == (_state&BGFX_STATE_RESERVED_MASK), "Do not set state reserved flags!");
s_ctx->setState(_state, _rgba);
}
void setCondition(OcclusionQueryHandle _handle, bool _visible)
{
BGFX_CHECK_MAIN_THREAD();
BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_OCCLUSION_QUERY)
, "Occlusion query is not supported, use bgfx::getCaps to test BGFX_CAPS_OCCLUSION_QUERY feature availability"
);
s_ctx->setCondition(_handle, _visible);
}
void setStencil(uint32_t _fstencil, uint32_t _bstencil)
{
BGFX_CHECK_MAIN_THREAD();
@ -3269,16 +3310,27 @@ again:
return submit(_id, handle);
}
uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth)
uint32_t submit(uint8_t _id, ProgramHandle _program, int32_t _depth)
{
BGFX_CHECK_MAIN_THREAD();
return s_ctx->submit(_id, _handle, _depth);
OcclusionQueryHandle handle = BGFX_INVALID_HANDLE;
return submit(_id, _program, handle, _depth);
}
uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
uint32_t submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth)
{
BGFX_CHECK_MAIN_THREAD();
return s_ctx->submit(_id, _handle, _indirectHandle, _start, _num, _depth);
BX_CHECK(false
|| !isValid(_occlusionQuery)
|| 0 != (g_caps.supported & BGFX_CAPS_OCCLUSION_QUERY)
, "Occlusion query is not supported, use bgfx::getCaps to test BGFX_CAPS_OCCLUSION_QUERY feature availability"
);
return s_ctx->submit(_id, _program, _occlusionQuery, _depth);
}
uint32_t submit(uint8_t _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
{
BGFX_CHECK_MAIN_THREAD();
return s_ctx->submit(_id, _program, _indirectHandle, _start, _num, _depth);
}
void setBuffer(uint8_t _stage, IndexBufferHandle _handle, Access::Enum _access)
@ -4011,6 +4063,12 @@ BGFX_C_API void bgfx_set_state(uint64_t _state, uint32_t _rgba)
bgfx::setState(_state, _rgba);
}
BGFX_C_API void bgfx_set_condition(bgfx_occlusion_query_handle_t _handle, bool _visible)
{
union { bgfx_occlusion_query_handle_t c; bgfx::OcclusionQueryHandle cpp; } handle = { _handle };
bgfx::setCondition(handle.cpp, _visible);
}
BGFX_C_API void bgfx_set_stencil(uint32_t _fstencil, uint32_t _bstencil)
{
bgfx::setStencil(_fstencil, _bstencil);
@ -4123,6 +4181,13 @@ BGFX_C_API uint32_t bgfx_submit(uint8_t _id, bgfx_program_handle_t _handle, int3
return bgfx::submit(_id, handle.cpp, _depth);
}
BGFX_C_API uint32_t bgfx_submit_occlusion_query(uint8_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, int32_t _depth)
{
union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } program = { _program };
union { bgfx_occlusion_query_handle c; bgfx::OcclusionQueryHandle cpp; } occlusionQuery = { _occlusionQuery };
return bgfx::submit(_id, program.cpp, occlusionQuery.cpp, _depth);
}
BGFX_C_API uint32_t bgfx_submit_indirect(uint8_t _id, bgfx_program_handle_t _handle, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
{
union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } handle = { _handle };

View File

@ -173,8 +173,12 @@ namespace stl
#define BGFX_MAX_COMPUTE_BINDINGS 8
#define BGFX_SAMPLER_DEFAULT_FLAGS UINT32_C(0x10000000)
#define BGFX_RESET_FORCE UINT32_C(0x80000000)
#define BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER UINT32_C(0x10000000)
#define BGFX_RESET_INTERNAL_FORCE UINT32_C(0x80000000)
#define BGFX_STATE_INTERNAL_SCISSOR UINT64_C(0x2000000000000000)
#define BGFX_STATE_INTERNAL_OCCLUSION_QUERY UINT64_C(0x4000000000000000)
#define BGFX_RENDERER_DIRECT3D9_NAME "Direct3D 9"
#define BGFX_RENDERER_DIRECT3D11_NAME "Direct3D 11"
@ -1093,7 +1097,7 @@ namespace bgfx
{
struct
{
uint32_t m_flags;
uint32_t m_textureFlags;
} m_draw;
struct
@ -1112,7 +1116,7 @@ namespace bgfx
{
m_constBegin = 0;
m_constEnd = 0;
m_flags = BGFX_STATE_DEFAULT;
m_stateFlags = BGFX_STATE_DEFAULT;
m_stencil = packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT);
m_rgba = 0;
m_matrix = 0;
@ -1123,28 +1127,29 @@ namespace bgfx
m_instanceDataOffset = 0;
m_instanceDataStride = 0;
m_numInstances = 1;
m_startIndirect = 0;
m_numIndirect = UINT16_MAX;
m_num = 1;
m_flags = BGFX_SUBMIT_EYE_FIRST;
m_scissor = UINT16_MAX;
m_startIndirect = 0;
m_numIndirect = UINT16_MAX;
m_num = 1;
m_submitFlags = BGFX_SUBMIT_EYE_FIRST;
m_scissor = UINT16_MAX;
m_vertexBuffer.idx = invalidHandle;
m_vertexDecl.idx = invalidHandle;
m_indexBuffer.idx = invalidHandle;
m_instanceDataBuffer.idx = invalidHandle;
m_indirectBuffer.idx = invalidHandle;
m_indirectBuffer.idx = invalidHandle;
m_occlusionQuery.idx = invalidHandle;
for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++ii)
{
Binding& bind = m_bind[ii];
bind.m_idx = invalidHandle;
bind.m_type = 0;
bind.m_un.m_draw.m_flags = 0;
bind.m_un.m_draw.m_textureFlags = 0;
}
}
Binding m_bind[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS];
uint64_t m_flags;
uint64_t m_stateFlags;
uint64_t m_stencil;
uint32_t m_rgba;
uint32_t m_constBegin;
@ -1163,11 +1168,12 @@ namespace bgfx
uint16_t m_scissor;
uint8_t m_submitFlags;
VertexBufferHandle m_vertexBuffer;
VertexDeclHandle m_vertexDecl;
IndexBufferHandle m_indexBuffer;
VertexBufferHandle m_instanceDataBuffer;
VertexBufferHandle m_vertexBuffer;
VertexDeclHandle m_vertexDecl;
IndexBufferHandle m_indexBuffer;
VertexBufferHandle m_instanceDataBuffer;
IndirectBufferHandle m_indirectBuffer;
OcclusionQueryHandle m_occlusionQuery;
};
struct RenderCompute
@ -1313,7 +1319,7 @@ namespace bgfx
void start()
{
m_flags = BGFX_STATE_NONE;
m_stateFlags = BGFX_STATE_NONE;
m_uniformBegin = 0;
m_uniformEnd = 0;
m_draw.clear();
@ -1361,10 +1367,16 @@ namespace bgfx
uint8_t blend = ( (_state&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT)&0xff;
// transparency sort order table
m_key.m_trans = "\x0\x1\x1\x2\x2\x1\x2\x1\x2\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1"[( (blend)&0xf) + (!!blend)];
m_draw.m_flags = _state;
m_draw.m_stateFlags = _state;
m_draw.m_rgba = _rgba;
}
void setCondition(OcclusionQueryHandle _handle, bool _visible)
{
m_draw.m_occlusionQuery = _handle;
BX_UNUSED(_visible);
}
void setStencil(uint32_t _fstencil, uint32_t _bstencil)
{
m_draw.m_stencil = packStencil(_fstencil, _bstencil);
@ -1473,8 +1485,8 @@ namespace bgfx
Binding& bind = m_draw.m_bind[_stage];
bind.m_idx = _handle.idx;
bind.m_type = uint8_t(Binding::Texture);
bind.m_un.m_draw.m_flags = (_flags&BGFX_SAMPLER_DEFAULT_FLAGS)
? BGFX_SAMPLER_DEFAULT_FLAGS
bind.m_un.m_draw.m_textureFlags = (_flags&BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER)
? BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER
: _flags
;
@ -1526,17 +1538,18 @@ namespace bgfx
m_discard = false;
m_draw.clear();
m_compute.clear();
m_flags = BGFX_STATE_NONE;
m_stateFlags = BGFX_STATE_NONE;
}
uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth);
uint32_t submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth);
uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
uint32_t submit(uint8_t _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth)
{
m_draw.m_startIndirect = _start;
m_draw.m_numIndirect = _num;
m_draw.m_indirectBuffer = _indirectHandle;
return submit(_id, _handle, _depth);
OcclusionQueryHandle handle = BGFX_INVALID_HANDLE;
return submit(_id, _program, handle, _depth);
}
uint32_t dispatch(uint8_t _id, ProgramHandle _handle, uint16_t _ngx, uint16_t _ngy, uint16_t _ngz, uint8_t _flags);
@ -1674,7 +1687,7 @@ namespace bgfx
RenderCompute m_compute;
uint32_t m_blitKeys[BGFX_CONFIG_MAX_BLIT_ITEMS+1];
BlitItem m_blitItem[BGFX_CONFIG_MAX_BLIT_ITEMS+1];
uint64_t m_flags;
uint64_t m_stateFlags;
uint32_t m_uniformBegin;
uint32_t m_uniformEnd;
uint32_t m_uniformMax;
@ -2037,7 +2050,7 @@ namespace bgfx
, uint16_t(m_resolution.m_width)
, uint16_t(m_resolution.m_height)
);
m_resolution.m_flags |= BGFX_RESET_FORCE;
m_resolution.m_flags |= BGFX_RESET_INTERNAL_FORCE;
}
}
}
@ -3279,6 +3292,18 @@ namespace bgfx
}
}
BGFX_API_FUNC(OcclusionQueryHandle createOcclusionQuery() )
{
OcclusionQueryHandle handle = { m_occlusionQueryHandle.alloc() };
return handle;
}
BGFX_API_FUNC(void destroyOcclusionQuery(OcclusionQueryHandle _handle) )
{
BGFX_CHECK_HANDLE("destroyOcclusionQuery", m_occlusionQueryHandle, _handle);
m_occlusionQueryHandle.free(_handle.idx);
}
BGFX_API_FUNC(void saveScreenShot(const char* _filePath) )
{
CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::SaveScreenShot);
@ -3435,6 +3460,11 @@ namespace bgfx
m_submit->setState(_state, _rgba);
}
BGFX_API_FUNC(void setCondition(OcclusionQueryHandle _handle, bool _visible) )
{
m_submit->setCondition(_handle, _visible);
}
BGFX_API_FUNC(void setStencil(uint32_t _fstencil, uint32_t _bstencil) )
{
m_submit->setStencil(_fstencil, _bstencil);
@ -3565,14 +3595,15 @@ namespace bgfx
m_submit->setTexture(_stage, _sampler, textureHandle, _flags);
}
BGFX_API_FUNC(uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth) )
BGFX_API_FUNC(uint32_t submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth) )
{
BGFX_CHECK_HANDLE_INVALID_OK("submit", m_programHandle, _handle);
BGFX_CHECK_HANDLE_INVALID_OK("submit", m_programHandle, _program);
BGFX_CHECK_HANDLE_INVALID_OK("submit", m_occlusionQueryHandle, _occlusionQuery);
if (BX_ENABLED(BGFX_CONFIG_DEBUG_UNIFORM) )
{
m_uniformSet.clear();
}
return m_submit->submit(_id, _handle, _depth);
return m_submit->submit(_id, _program, _occlusionQuery, _depth);
}
BGFX_API_FUNC(uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth) )
@ -3797,6 +3828,7 @@ namespace bgfx
bx::HandleAllocT<BGFX_CONFIG_MAX_TEXTURES> m_textureHandle;
bx::HandleAllocT<BGFX_CONFIG_MAX_FRAME_BUFFERS> m_frameBufferHandle;
bx::HandleAllocT<BGFX_CONFIG_MAX_UNIFORMS> m_uniformHandle;
bx::HandleAllocT<BGFX_CONFIG_MAX_OCCUSION_QUERIES> m_occlusionQueryHandle;
struct ShaderRef
{

View File

@ -269,6 +269,10 @@
# define BGFX_CONFIG_MAX_UNIFORMS 512
#endif // BGFX_CONFIG_MAX_UNIFORMS
#ifndef BGFX_CONFIG_MAX_OCCUSION_QUERIES
# define BGFX_CONFIG_MAX_OCCUSION_QUERIES 256
#endif // BGFX_CONFIG_MAX_OCCUSION_QUERIES
#ifndef BGFX_CONFIG_MAX_COMMAND_BUFFER_SIZE
# define BGFX_CONFIG_MAX_COMMAND_BUFFER_SIZE (64<<10)
#endif // BGFX_CONFIG_MAX_COMMAND_BUFFER_SIZE

View File

@ -1158,6 +1158,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
| BGFX_CAPS_DRAW_INDIRECT
| BGFX_CAPS_TEXTURE_BLIT
| BGFX_CAPS_TEXTURE_READ_BACK
| BGFX_CAPS_OCCLUSION_QUERY
);
if (m_featureLevel <= D3D_FEATURE_LEVEL_9_2)
@ -1940,7 +1941,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
setShaderUniform(flags, predefined.m_loc, proj, 4);
commitShaderConstants();
m_textures[_blitter.m_texture.idx].commit(0, BGFX_SAMPLER_DEFAULT_FLAGS, NULL);
m_textures[_blitter.m_texture.idx].commit(0, BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER, NULL);
commitTextureStage();
}
@ -1964,6 +1965,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
ovrPreReset();
m_gpuTimer.preReset();
m_occlusionQuery.preReset();
if (NULL == g_platformData.backBufferDS)
{
@ -2008,6 +2010,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
}
m_gpuTimer.postReset();
m_occlusionQuery.postReset();
ovrPostReset();
@ -2159,7 +2162,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
|| m_resolution.m_height != _resolution.m_height
|| m_resolution.m_flags != flags)
{
flags &= ~BGFX_RESET_FORCE;
flags &= ~BGFX_RESET_INTERNAL_FORCE;
bool resize = true
&& !BX_ENABLED(BX_PLATFORM_WINRT) // can't use ResizeBuffers on Windows Phone
@ -2726,6 +2729,12 @@ BX_PRAGMA_DIAGNOSTIC_POP();
return sampler;
}
bool isVisible(OcclusionQueryHandle _handle)
{
m_occlusionQuery.resolve();
return m_occlusion[_handle.idx];
}
DXGI_FORMAT getBufferFormat()
{
#if BX_PLATFORM_WINRT
@ -3296,6 +3305,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
ID3D11DeviceContext* m_deviceCtx;
ID3D11InfoQueue* m_infoQueue;
TimerQueryD3D11 m_gpuTimer;
OcclusionQueryD3D11 m_occlusionQuery;
ID3D11RenderTargetView* m_backBufferColor;
ID3D11DepthStencilView* m_backBufferDepthStencil;
@ -3324,6 +3334,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
TextureD3D11 m_textures[BGFX_CONFIG_MAX_TEXTURES];
VertexDecl m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS];
FrameBufferD3D11 m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS];
bool m_occlusion[BGFX_CONFIG_MAX_OCCUSION_QUERIES];
void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS];
Matrix4 m_predefinedUniforms[PredefinedUniform::Count];
UniformRegistry m_uniformReg;
@ -4149,7 +4160,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
{
TextureStage& ts = s_renderD3D11->m_textureStage;
ts.m_srv[_stage] = m_srv;
uint32_t flags = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags)
uint32_t flags = 0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags)
? _flags
: m_flags
;
@ -4516,7 +4527,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
Frame& frame = m_frame[m_control.m_read];
uint64_t finish;
HRESULT hr = deviceCtx->GetData(frame.m_end, &finish, sizeof(finish), 0);
HRESULT hr = deviceCtx->GetData(frame.m_end, &finish, sizeof(finish), D3D11_ASYNC_GETDATA_DONOTFLUSH);
if (S_OK == hr)
{
m_control.consume(1);
@ -4543,6 +4554,70 @@ BX_PRAGMA_DIAGNOSTIC_POP();
return false;
}
void OcclusionQueryD3D11::postReset()
{
ID3D11Device* device = s_renderD3D11->m_device;
D3D11_QUERY_DESC desc;
desc.Query = D3D11_QUERY_OCCLUSION;
desc.MiscFlags = 0;
for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii)
{
Query& query = m_query[ii];
DX_CHECK(device->CreateQuery(&desc, &query.m_ptr) );
}
}
void OcclusionQueryD3D11::preReset()
{
for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii)
{
Query& query = m_query[ii];
DX_RELEASE(query.m_ptr, 0);
}
}
void OcclusionQueryD3D11::begin(OcclusionQueryHandle _handle)
{
while (0 == m_control.reserve(1) )
{
resolve(true);
}
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
Query& query = m_query[m_control.m_current];
deviceCtx->Begin(query.m_ptr);
query.m_handle = _handle;
}
void OcclusionQueryD3D11::end()
{
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
Query& query = m_query[m_control.m_current];
deviceCtx->End(query.m_ptr);
m_control.commit(1);
}
void OcclusionQueryD3D11::resolve(bool _wait)
{
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
while (0 != m_control.available() )
{
Query& query = m_query[m_control.m_read];
uint64_t result = 0;
HRESULT hr = deviceCtx->GetData(query.m_ptr, &result, sizeof(result), _wait ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
if (S_FALSE == hr)
{
break;
}
s_renderD3D11->m_occlusion[query.m_handle.idx] = 0 < result;
m_control.consume(1);
}
}
void RendererContextD3D11::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter)
{
PIX_BEGINEVENT(D3DCOLOR_RGBA(0xff, 0x00, 0x00, 0xff), L"rendererSubmit");
@ -4572,7 +4647,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
RenderDraw currentState;
currentState.clear();
currentState.m_flags = BGFX_STATE_NONE;
currentState.m_stateFlags = BGFX_STATE_NONE;
currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE);
_render->m_hmdInitialized = m_ovr.isInitialized();
@ -4612,6 +4687,8 @@ BX_PRAGMA_DIAGNOSTIC_POP();
uint32_t statsNumIndices = 0;
uint32_t statsKeyType[2] = {};
m_occlusionQuery.resolve();
if (0 == (_render->m_debug&BGFX_DEBUG_IFH) )
{
// reset the framebuffer to be the backbuffer; depending on the swap effect,
@ -4965,8 +5042,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
PIX_BEGINEVENT(D3DCOLOR_RGBA(0xff, 0x00, 0x00, 0xff), viewNameW);
}
wasCompute = false;
programIdx = invalidHandle;
m_currentProgram = NULL;
@ -4975,10 +5050,18 @@ BX_PRAGMA_DIAGNOSTIC_POP();
const RenderDraw& draw = renderItem.draw;
const uint64_t newFlags = draw.m_flags;
uint64_t changedFlags = currentState.m_flags ^ draw.m_flags;
const bool hasOcclusionQuery = 0 != (draw.m_stateFlags & BGFX_STATE_INTERNAL_OCCLUSION_QUERY);
if (isValid(draw.m_occlusionQuery)
&& !hasOcclusionQuery
&& !isVisible(draw.m_occlusionQuery) )
{
continue;
}
const uint64_t newFlags = draw.m_stateFlags;
uint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags;
changedFlags |= currentState.m_rgba != draw.m_rgba ? BGFX_D3D11_BLEND_STATE_MASK : 0;
currentState.m_flags = newFlags;
currentState.m_stateFlags = newFlags;
const uint64_t newStencil = draw.m_stencil;
uint64_t changedStencil = currentState.m_stencil ^ draw.m_stencil;
@ -4987,12 +5070,14 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (resetState)
{
wasCompute = false;
currentState.clear();
currentState.m_scissor = !draw.m_scissor;
changedFlags = BGFX_STATE_MASK;
changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
currentState.m_flags = newFlags;
currentState.m_stencil = newStencil;
currentState.m_stateFlags = newFlags;
currentState.m_stencil = newStencil;
setBlendState(newFlags);
setDepthStencilState(newFlags, packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT) );
@ -5156,13 +5241,13 @@ BX_PRAGMA_DIAGNOSTIC_POP();
const Binding& bind = draw.m_bind[stage];
Binding& current = currentState.m_bind[stage];
if (current.m_idx != bind.m_idx
|| current.m_un.m_draw.m_flags != bind.m_un.m_draw.m_flags
|| current.m_un.m_draw.m_textureFlags != bind.m_un.m_draw.m_textureFlags
|| programChanged)
{
if (invalidHandle != bind.m_idx)
{
TextureD3D11& texture = m_textures[bind.m_idx];
texture.commit(stage, bind.m_un.m_draw.m_flags, _render->m_colorPalette);
texture.commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette);
}
else
{
@ -5261,6 +5346,11 @@ BX_PRAGMA_DIAGNOSTIC_POP();
uint32_t numPrimsRendered = 0;
uint32_t numDrawIndirect = 0;
if (hasOcclusionQuery)
{
m_occlusionQuery.begin(draw.m_occlusionQuery);
}
if (isValid(draw.m_indirectBuffer) )
{
const VertexBufferD3D11& vb = m_vertexBuffers[draw.m_indirectBuffer.idx];
@ -5369,6 +5459,11 @@ BX_PRAGMA_DIAGNOSTIC_POP();
);
}
}
if (hasOcclusionQuery)
{
m_occlusionQuery.end();
}
}
statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted;
@ -5540,6 +5635,9 @@ BX_PRAGMA_DIAGNOSTIC_POP();
tvm.printf(10, pos++, 0x8e, " DVB size: %7d ", _render->m_vboffset);
tvm.printf(10, pos++, 0x8e, " DIB size: %7d ", _render->m_iboffset);
pos++;
tvm.printf(10, pos++, 0x8e, " Occlusion queries: %3d ", m_occlusionQuery.m_control.available() );
pos++;
tvm.printf(10, pos++, 0x8e, " State cache: ");
tvm.printf(10, pos++, 0x8e, " Blend | DepthS | Input | Raster | Sampler ");

View File

@ -307,6 +307,29 @@ namespace bgfx { namespace d3d11
bx::RingBufferControl m_control;
};
struct OcclusionQueryD3D11
{
OcclusionQueryD3D11()
: m_control(BX_COUNTOF(m_query) )
{
}
void postReset();
void preReset();
void begin(OcclusionQueryHandle _handle);
void end();
void resolve(bool _wait = false);
struct Query
{
ID3D11Query* m_ptr;
OcclusionQueryHandle m_handle;
};
Query m_query[BGFX_CONFIG_MAX_OCCUSION_QUERIES];
bx::RingBufferControl m_control;
};
} /* namespace d3d11 */ } // namespace bgfx
#endif // BGFX_RENDERER_D3D11_H_HEADER_GUARD

View File

@ -1728,7 +1728,7 @@ data.NumQualityLevels = 0;
|| m_resolution.m_height != _resolution.m_height
|| m_resolution.m_flags != flags)
{
flags &= ~BGFX_RESET_FORCE;
flags &= ~BGFX_RESET_INTERNAL_FORCE;
bool resize = (m_resolution.m_flags&BGFX_RESET_MSAA_MASK) == (_resolution.m_flags&BGFX_RESET_MSAA_MASK);
@ -4349,8 +4349,8 @@ data.NumQualityLevels = 0;
RenderDraw currentState;
currentState.clear();
currentState.m_flags = BGFX_STATE_NONE;
currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE);
currentState.m_stateFlags = BGFX_STATE_NONE;
currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE);
_render->m_hmdInitialized = false;
@ -4718,9 +4718,9 @@ data.NumQualityLevels = 0;
const RenderDraw& draw = renderItem.draw;
const uint64_t newFlags = draw.m_flags;
uint64_t changedFlags = currentState.m_flags ^ draw.m_flags;
currentState.m_flags = newFlags;
const uint64_t newFlags = draw.m_stateFlags;
uint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags;
currentState.m_stateFlags = newFlags;
const uint64_t newStencil = draw.m_stencil;
uint64_t changedStencil = (currentState.m_stencil ^ draw.m_stencil) & BGFX_STENCIL_FUNC_REF_MASK;
@ -4765,8 +4765,8 @@ data.NumQualityLevels = 0;
currentState.m_scissor = !draw.m_scissor;
changedFlags = BGFX_STATE_MASK;
changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
currentState.m_flags = newFlags;
currentState.m_stencil = newStencil;
currentState.m_stateFlags = newFlags;
currentState.m_stencil = newStencil;
const uint64_t pt = newFlags&BGFX_STATE_PT_MASK;
primIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT);
@ -4776,7 +4776,7 @@ data.NumQualityLevels = 0;
if (isValid(draw.m_vertexBuffer) )
{
const uint64_t state = draw.m_flags;
const uint64_t state = draw.m_stateFlags;
bool hasFactor = 0
|| f0 == (state & f0)
|| f1 == (state & f1)
@ -4825,8 +4825,8 @@ data.NumQualityLevels = 0;
TextureD3D12& texture = m_textures[bind.m_idx];
texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ);
scratchBuffer.allocSrv(srvHandle[stage], texture);
samplerFlags[stage] = (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & bind.m_un.m_draw.m_flags)
? bind.m_un.m_draw.m_flags
samplerFlags[stage] = (0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & bind.m_un.m_draw.m_textureFlags)
? bind.m_un.m_draw.m_textureFlags
: texture.m_flags
) & (BGFX_TEXTURE_SAMPLER_BITS_MASK|BGFX_TEXTURE_BORDER_COLOR_MASK)
;

View File

@ -285,6 +285,7 @@ namespace bgfx { namespace d3d9
, m_nvidia(false)
, m_instancingSupport(false)
, m_timerQuerySupport(false)
, m_occlusionQuerySupport(false)
, m_rtMsaa(false)
{
}
@ -501,6 +502,26 @@ namespace bgfx { namespace d3d9
DX_CHECK(m_device->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&m_deviceEx) );
}
{
IDirect3DQuery9* timerQueryTest[3] = {};
m_timerQuerySupport = true
&& SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMPDISJOINT, &timerQueryTest[0]) )
&& SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &timerQueryTest[1]) )
&& SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMPFREQ, &timerQueryTest[2]) )
;
DX_RELEASE(timerQueryTest[0], 0);
DX_RELEASE(timerQueryTest[1], 0);
DX_RELEASE(timerQueryTest[2], 0);
}
{
IDirect3DQuery9* occlusionQueryTest;
m_occlusionQuerySupport = true
&& SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQueryTest) )
;
DX_RELEASE(occlusionQueryTest, 0);
}
DX_CHECK(m_device->GetDeviceCaps(&m_caps) );
// For shit GPUs that can create DX9 device but can't do simple stuff. GTFO!
@ -538,6 +559,7 @@ namespace bgfx { namespace d3d9
| ( (UINT16_MAX < m_caps.MaxVertexIndex) ? BGFX_CAPS_INDEX32 : 0)
| ( (m_caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) ? BGFX_CAPS_TEXTURE_BLIT : 0)
| BGFX_CAPS_TEXTURE_READ_BACK
| (m_occlusionQuerySupport ? BGFX_CAPS_OCCLUSION_QUERY : 0)
);
g_caps.maxTextureSize = uint16_t(bx::uint32_min(m_caps.MaxTextureWidth, m_caps.MaxTextureHeight) );
// g_caps.maxVertexIndex = m_caps.MaxVertexIndex;
@ -694,18 +716,6 @@ namespace bgfx { namespace d3d9
m_fmtDepth = D3DFMT_D24FS8;
#endif // BX_PLATFORM_WINDOWS
{
IDirect3DQuery9* timerQueryTest[3] = {};
m_timerQuerySupport = true
&& SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMPDISJOINT, &timerQueryTest[0]) )
&& SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &timerQueryTest[1]) )
&& SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMPFREQ, &timerQueryTest[2]) )
;
DX_RELEASE(timerQueryTest[0], 0);
DX_RELEASE(timerQueryTest[1], 0);
DX_RELEASE(timerQueryTest[2], 0);
}
{
IDirect3DSwapChain9* swapChain;
DX_CHECK(m_device->GetSwapChain(0, &swapChain) );
@ -1162,7 +1172,7 @@ namespace bgfx { namespace d3d9
uint8_t flags = predefined.m_type;
setShaderUniform(flags, predefined.m_loc, proj, 4);
m_textures[_blitter.m_texture.idx].commit(0, BGFX_SAMPLER_DEFAULT_FLAGS, NULL);
m_textures[_blitter.m_texture.idx].commit(0, BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER, NULL);
}
void blitRender(TextVideoMemBlitter& _blitter, uint32_t _numIndices) BX_OVERRIDE
@ -1223,7 +1233,7 @@ namespace bgfx { namespace d3d9
|| m_resolution.m_height != _resolution.m_height
|| m_resolution.m_flags != flags)
{
flags &= ~BGFX_RESET_FORCE;
flags &= ~BGFX_RESET_INTERNAL_FORCE;
m_resolution = _resolution;
m_resolution.m_flags = flags;
@ -1434,6 +1444,11 @@ namespace bgfx { namespace d3d9
m_gpuTimer.preReset();
}
if (m_occlusionQuerySupport)
{
m_occlusionQuery.preReset();
}
for (uint32_t ii = 0; ii < BX_COUNTOF(m_indexBuffers); ++ii)
{
m_indexBuffers[ii].preReset();
@ -1467,6 +1482,11 @@ namespace bgfx { namespace d3d9
m_gpuTimer.postReset();
}
if (m_occlusionQuerySupport)
{
m_occlusionQuery.postReset();
}
capturePostReset();
for (uint32_t ii = 0; ii < BX_COUNTOF(m_indexBuffers); ++ii)
@ -1545,6 +1565,12 @@ namespace bgfx { namespace d3d9
}
}
bool isVisible(OcclusionQueryHandle _handle)
{
m_occlusionQuery.resolve();
return m_occlusion[_handle.idx];
}
void capturePreReset()
{
if (NULL != m_captureSurface)
@ -1937,10 +1963,11 @@ namespace bgfx { namespace d3d9
IDirect3D9Ex* m_d3d9ex;
IDirect3DDevice9Ex* m_deviceEx;
IDirect3D9* m_d3d9;
IDirect3DDevice9* m_device;
IDirect3DQuery9* m_flushQuery;
TimerQueryD3D9 m_gpuTimer;
IDirect3D9* m_d3d9;
IDirect3DDevice9* m_device;
IDirect3DQuery9* m_flushQuery;
TimerQueryD3D9 m_gpuTimer;
OcclusionQueryD3D9 m_occlusionQuery;
D3DPOOL m_pool;
IDirect3DSwapChain9* m_swapChain;
@ -1969,6 +1996,7 @@ namespace bgfx { namespace d3d9
bool m_nvidia;
bool m_instancingSupport;
bool m_timerQuerySupport;
bool m_occlusionQuerySupport;
D3DFORMAT m_fmtDepth;
@ -1979,6 +2007,7 @@ namespace bgfx { namespace d3d9
TextureD3D9 m_textures[BGFX_CONFIG_MAX_TEXTURES];
VertexDeclD3D9 m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS];
FrameBufferD3D9 m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS];
bool m_occlusion[BGFX_CONFIG_MAX_OCCUSION_QUERIES];
UniformRegistry m_uniformReg;
void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS];
@ -2950,7 +2979,7 @@ namespace bgfx { namespace d3d9
void TextureD3D9::commit(uint8_t _stage, uint32_t _flags, const float _palette[][4])
{
uint32_t flags = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags)
uint32_t flags = 0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags)
? _flags
: m_flags
;
@ -3361,6 +3390,63 @@ namespace bgfx { namespace d3d9
return false;
}
void OcclusionQueryD3D9::postReset()
{
IDirect3DDevice9* device = s_renderD3D9->m_device;
for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii)
{
Query& query = m_query[ii];
DX_CHECK(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query.m_ptr) );
}
}
void OcclusionQueryD3D9::preReset()
{
for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii)
{
Query& query = m_query[ii];
DX_RELEASE(query.m_ptr, 0);
}
}
void OcclusionQueryD3D9::begin(OcclusionQueryHandle _handle)
{
while (0 == m_control.reserve(1) )
{
resolve(true);
}
Query& query = m_query[m_control.m_current];
query.m_ptr->Issue(D3DISSUE_BEGIN);
query.m_handle = _handle;
}
void OcclusionQueryD3D9::end()
{
Query& query = m_query[m_control.m_current];
query.m_ptr->Issue(D3DISSUE_END);
m_control.commit(1);
}
void OcclusionQueryD3D9::resolve(bool)
{
while (0 != m_control.available() )
{
Query& query = m_query[m_control.m_read];
uint64_t result;
HRESULT hr = query.m_ptr->GetData(&result, sizeof(result), 0);
if (S_FALSE == hr)
{
break;
}
s_renderD3D9->m_occlusion[query.m_handle.idx] = 0 < result;
m_control.consume(1);
}
}
void RendererContextD3D9::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter)
{
IDirect3DDevice9* device = m_device;
@ -3394,8 +3480,8 @@ namespace bgfx { namespace d3d9
RenderDraw currentState;
currentState.clear();
currentState.m_flags = BGFX_STATE_NONE;
currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE);
currentState.m_stateFlags = BGFX_STATE_NONE;
currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE);
ViewState viewState(_render, false);
@ -3445,9 +3531,17 @@ namespace bgfx { namespace d3d9
const RenderDraw& draw = _render->m_renderItem[_render->m_sortValues[item] ].draw;
const uint64_t newFlags = draw.m_flags;
uint64_t changedFlags = currentState.m_flags ^ draw.m_flags;
currentState.m_flags = newFlags;
const bool hasOcclusionQuery = 0 != (draw.m_stateFlags & BGFX_STATE_INTERNAL_OCCLUSION_QUERY);
if (isValid(draw.m_occlusionQuery)
&& !hasOcclusionQuery
&& !isVisible(draw.m_occlusionQuery) )
{
continue;
}
const uint64_t newFlags = draw.m_stateFlags;
uint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags;
currentState.m_stateFlags = newFlags;
const uint64_t newStencil = draw.m_stencil;
uint64_t changedStencil = currentState.m_stencil ^ draw.m_stencil;
@ -3459,8 +3553,8 @@ namespace bgfx { namespace d3d9
currentState.m_scissor = !draw.m_scissor;
changedFlags = BGFX_STATE_MASK;
changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
currentState.m_flags = newFlags;
currentState.m_stencil = newStencil;
currentState.m_stateFlags = newFlags;
currentState.m_stencil = newStencil;
PIX_ENDEVENT();
PIX_BEGINEVENT(D3DCOLOR_RGBA(0xff, 0x00, 0x00, 0xff), s_viewNameW[key.m_view]);
@ -3807,12 +3901,12 @@ namespace bgfx { namespace d3d9
const Binding& bind = draw.m_bind[stage];
Binding& current = currentState.m_bind[stage];
if (current.m_idx != bind.m_idx
|| current.m_un.m_draw.m_flags != bind.m_un.m_draw.m_flags
|| current.m_un.m_draw.m_textureFlags != bind.m_un.m_draw.m_textureFlags
|| programChanged)
{
if (invalidHandle != bind.m_idx)
{
m_textures[bind.m_idx].commit(stage, bind.m_un.m_draw.m_flags, _render->m_colorPalette);
m_textures[bind.m_idx].commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette);
}
else
{
@ -3902,6 +3996,11 @@ namespace bgfx { namespace d3d9
uint32_t numInstances = 0;
uint32_t numPrimsRendered = 0;
if (hasOcclusionQuery)
{
m_occlusionQuery.begin(draw.m_occlusionQuery);
}
if (isValid(draw.m_indexBuffer) )
{
if (UINT32_MAX == draw.m_numIndices)
@ -3949,6 +4048,11 @@ namespace bgfx { namespace d3d9
) );
}
if (hasOcclusionQuery)
{
m_occlusionQuery.end();
}
statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted;
statsNumPrimsRendered[primIndex] += numPrimsRendered;
statsNumInstances[primIndex] += numInstances;

View File

@ -357,6 +357,7 @@ namespace bgfx { namespace d3d9
IDirect3DVolumeTexture9* m_staging3d;
IDirect3DCubeTexture9* m_stagingCube;
};
uint32_t m_flags;
uint32_t m_width;
uint32_t m_height;
@ -429,6 +430,29 @@ namespace bgfx { namespace d3d9
bx::RingBufferControl m_control;
};
struct OcclusionQueryD3D9
{
OcclusionQueryD3D9()
: m_control(BX_COUNTOF(m_query) )
{
}
void postReset();
void preReset();
void begin(OcclusionQueryHandle _handle);
void end();
void resolve(bool _wait = false);
struct Query
{
IDirect3DQuery9* m_ptr;
OcclusionQueryHandle m_handle;
};
Query m_query[BGFX_CONFIG_MAX_OCCUSION_QUERIES];
bx::RingBufferControl m_control;
};
} /* namespace d3d9 */ } // namespace bgfx
#endif // BGFX_RENDERER_D3D9_H_HEADER_GUARD

View File

@ -2350,7 +2350,7 @@ namespace bgfx { namespace gl
|| m_resolution.m_height != _resolution.m_height
|| m_resolution.m_flags != flags)
{
flags &= ~BGFX_RESET_FORCE;
flags &= ~BGFX_RESET_INTERNAL_FORCE;
m_resolution = _resolution;
m_resolution.m_flags = flags;
@ -2587,7 +2587,7 @@ namespace bgfx { namespace gl
if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
|| BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES >= 30) )
{
if (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) )
if (0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags) )
{
const uint32_t index = (_flags & BGFX_TEXTURE_BORDER_COLOR_MASK) >> BGFX_TEXTURE_BORDER_COLOR_SHIFT;
@ -4282,7 +4282,7 @@ namespace bgfx { namespace gl
;
}
const uint32_t flags = (0 != (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) ? m_flags : _flags) & BGFX_TEXTURE_SAMPLER_BITS_MASK;
const uint32_t flags = (0 != (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags) ? m_flags : _flags) & BGFX_TEXTURE_SAMPLER_BITS_MASK;
bool hasBorderColor = false;
bx::HashMurmur2A murmur;
@ -4361,7 +4361,7 @@ namespace bgfx { namespace gl
void TextureGL::commit(uint32_t _stage, uint32_t _flags, const float _palette[][4])
{
const uint32_t flags = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags)
const uint32_t flags = 0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags)
? _flags
: m_flags
;
@ -5163,8 +5163,8 @@ namespace bgfx { namespace gl
RenderDraw currentState;
currentState.clear();
currentState.m_flags = BGFX_STATE_NONE;
currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE);
currentState.m_stateFlags = BGFX_STATE_NONE;
currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE);
_render->m_hmdInitialized = m_ovr.isInitialized();
@ -5505,9 +5505,9 @@ namespace bgfx { namespace gl
const RenderDraw& draw = renderItem.draw;
const uint64_t newFlags = draw.m_flags;
uint64_t changedFlags = currentState.m_flags ^ draw.m_flags;
currentState.m_flags = newFlags;
const uint64_t newFlags = draw.m_stateFlags;
uint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags;
currentState.m_stateFlags = newFlags;
const uint64_t newStencil = draw.m_stencil;
uint64_t changedStencil = currentState.m_stencil ^ draw.m_stencil;
@ -5519,8 +5519,8 @@ namespace bgfx { namespace gl
currentState.m_scissor = !draw.m_scissor;
changedFlags = BGFX_STATE_MASK;
changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
currentState.m_flags = newFlags;
currentState.m_stencil = newStencil;
currentState.m_stateFlags = newFlags;
currentState.m_stencil = newStencil;
}
uint16_t scissor = draw.m_scissor;
@ -5830,13 +5830,13 @@ namespace bgfx { namespace gl
const Binding& bind = draw.m_bind[stage];
Binding& current = currentState.m_bind[stage];
if (current.m_idx != bind.m_idx
|| current.m_un.m_draw.m_flags != bind.m_un.m_draw.m_flags
|| current.m_un.m_draw.m_textureFlags != bind.m_un.m_draw.m_textureFlags
|| programChanged)
{
if (invalidHandle != bind.m_idx)
{
TextureGL& texture = m_textures[bind.m_idx];
texture.commit(stage, bind.m_un.m_draw.m_flags, _render->m_colorPalette);
texture.commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette);
}
}