libobs: Add GPU timestamp query support
This change only wraps the functionality. I have rough code to exercise the the query functionality, but that part is not really clean enough to submit.
This commit is contained in:
@@ -225,6 +225,29 @@ void gs_swap_chain::Rebuild(ID3D11Device *dev)
|
||||
Init();
|
||||
}
|
||||
|
||||
void gs_timer::Rebuild(ID3D11Device *dev)
|
||||
{
|
||||
D3D11_QUERY_DESC desc;
|
||||
desc.Query = D3D11_QUERY_TIMESTAMP;
|
||||
desc.MiscFlags = 0;
|
||||
HRESULT hr = dev->CreateQuery(&desc, &query_begin);
|
||||
if (FAILED(hr))
|
||||
throw HRError("Failed to create timer", hr);
|
||||
hr = dev->CreateQuery(&desc, &query_end);
|
||||
if (FAILED(hr))
|
||||
throw HRError("Failed to create timer", hr);
|
||||
}
|
||||
|
||||
void gs_timer_range::Rebuild(ID3D11Device *dev)
|
||||
{
|
||||
D3D11_QUERY_DESC desc;
|
||||
desc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
||||
desc.MiscFlags = 0;
|
||||
HRESULT hr = dev->CreateQuery(&desc, &query_disjoint);
|
||||
if (FAILED(hr))
|
||||
throw HRError("Failed to create timer", hr);
|
||||
}
|
||||
|
||||
void SavedBlendState::Rebuild(ID3D11Device *dev)
|
||||
{
|
||||
HRESULT hr = dev->CreateBlendState(&bd, &state);
|
||||
@@ -296,6 +319,12 @@ try {
|
||||
case gs_type::gs_swap_chain:
|
||||
((gs_swap_chain *)obj)->Release();
|
||||
break;
|
||||
case gs_type::gs_timer:
|
||||
((gs_timer *)obj)->Release();
|
||||
break;
|
||||
case gs_type::gs_timer_range:
|
||||
((gs_timer_range *)obj)->Release();
|
||||
break;
|
||||
}
|
||||
|
||||
obj = obj->next;
|
||||
@@ -372,6 +401,12 @@ try {
|
||||
case gs_type::gs_swap_chain:
|
||||
((gs_swap_chain *)obj)->Rebuild(dev);
|
||||
break;
|
||||
case gs_type::gs_timer:
|
||||
((gs_timer *)obj)->Rebuild(dev);
|
||||
break;
|
||||
case gs_type::gs_timer_range:
|
||||
((gs_timer_range *)obj)->Rebuild(dev);
|
||||
break;
|
||||
}
|
||||
|
||||
obj = obj->next;
|
||||
|
@@ -1120,6 +1120,34 @@ gs_indexbuffer_t *device_indexbuffer_create(gs_device_t *device,
|
||||
return buffer;
|
||||
}
|
||||
|
||||
gs_timer_t *device_timer_create(gs_device_t *device)
|
||||
{
|
||||
gs_timer *timer = NULL;
|
||||
try {
|
||||
timer = new gs_timer(device);
|
||||
} catch (HRError error) {
|
||||
blog(LOG_ERROR, "device_timer_create (D3D11): %s (%08lX)",
|
||||
error.str, error.hr);
|
||||
LogD3D11ErrorDetails(error, device);
|
||||
}
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
gs_timer_range_t *device_timer_range_create(gs_device_t *device)
|
||||
{
|
||||
gs_timer_range *range = NULL;
|
||||
try {
|
||||
range = new gs_timer_range(device);
|
||||
} catch (HRError error) {
|
||||
blog(LOG_ERROR, "device_timer_range_create (D3D11): %s (%08lX)",
|
||||
error.str, error.hr);
|
||||
LogD3D11ErrorDetails(error, device);
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
enum gs_texture_type device_get_texture_type(const gs_texture_t *texture)
|
||||
{
|
||||
return texture->type;
|
||||
@@ -2232,6 +2260,88 @@ enum gs_index_type gs_indexbuffer_get_type(const gs_indexbuffer_t *indexbuffer)
|
||||
return indexbuffer->type;
|
||||
}
|
||||
|
||||
void gs_timer_destroy(gs_timer_t *timer)
|
||||
{
|
||||
delete timer;
|
||||
}
|
||||
|
||||
void gs_timer_begin(gs_timer_t *timer)
|
||||
{
|
||||
timer->device->context->End(timer->query_begin);
|
||||
}
|
||||
|
||||
void gs_timer_end(gs_timer_t *timer)
|
||||
{
|
||||
timer->device->context->End(timer->query_end);
|
||||
}
|
||||
|
||||
bool gs_timer_get_data(gs_timer_t *timer, uint64_t *ticks)
|
||||
{
|
||||
uint64_t begin, end;
|
||||
HRESULT hr_begin, hr_end;
|
||||
do {
|
||||
hr_begin = timer->device->context->GetData(
|
||||
timer->query_begin, &begin, sizeof(begin), 0);
|
||||
} while (hr_begin == S_FALSE);
|
||||
do {
|
||||
hr_end = timer->device->context->GetData(timer->query_end, &end,
|
||||
sizeof(end), 0);
|
||||
} while (hr_end == S_FALSE);
|
||||
|
||||
const bool succeeded = SUCCEEDED(hr_begin) && SUCCEEDED(hr_end);
|
||||
if (succeeded)
|
||||
*ticks = end - begin;
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
void gs_timer_range_destroy(gs_timer_range_t *range)
|
||||
{
|
||||
delete range;
|
||||
}
|
||||
|
||||
void gs_timer_range_begin(gs_timer_range_t *range)
|
||||
{
|
||||
range->device->context->Begin(range->query_disjoint);
|
||||
}
|
||||
|
||||
void gs_timer_range_end(gs_timer_range_t *range)
|
||||
{
|
||||
range->device->context->End(range->query_disjoint);
|
||||
}
|
||||
|
||||
bool gs_timer_range_get_data(gs_timer_range_t *range, bool *disjoint,
|
||||
uint64_t *frequency)
|
||||
{
|
||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timestamp_disjoint;
|
||||
HRESULT hr;
|
||||
do {
|
||||
hr = range->device->context->GetData(range->query_disjoint,
|
||||
×tamp_disjoint,
|
||||
sizeof(timestamp_disjoint),
|
||||
0);
|
||||
} while (hr == S_FALSE);
|
||||
|
||||
const bool succeeded = SUCCEEDED(hr);
|
||||
if (succeeded) {
|
||||
*disjoint = timestamp_disjoint.Disjoint;
|
||||
*frequency = timestamp_disjoint.Frequency;
|
||||
}
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
gs_timer::gs_timer(gs_device_t *device) : gs_obj(device, gs_type::gs_timer)
|
||||
{
|
||||
Rebuild(device->device);
|
||||
}
|
||||
|
||||
gs_timer_range::gs_timer_range(gs_device_t *device)
|
||||
: gs_obj(device, gs_type::gs_timer_range)
|
||||
{
|
||||
Rebuild(device->device);
|
||||
}
|
||||
|
||||
extern "C" EXPORT bool device_gdi_texture_available(void)
|
||||
{
|
||||
return true;
|
||||
|
@@ -292,6 +292,8 @@ enum class gs_type {
|
||||
gs_pixel_shader,
|
||||
gs_duplicator,
|
||||
gs_swap_chain,
|
||||
gs_timer,
|
||||
gs_timer_range,
|
||||
};
|
||||
|
||||
struct gs_obj {
|
||||
@@ -373,6 +375,31 @@ struct gs_index_buffer : gs_obj {
|
||||
void *indices, size_t num, uint32_t flags);
|
||||
};
|
||||
|
||||
struct gs_timer : gs_obj {
|
||||
ComPtr<ID3D11Query> query_begin;
|
||||
ComPtr<ID3D11Query> query_end;
|
||||
|
||||
void Rebuild(ID3D11Device *dev);
|
||||
|
||||
inline void Release()
|
||||
{
|
||||
query_begin.Release();
|
||||
query_end.Release();
|
||||
}
|
||||
|
||||
gs_timer(gs_device_t *device);
|
||||
};
|
||||
|
||||
struct gs_timer_range : gs_obj {
|
||||
ComPtr<ID3D11Query> query_disjoint;
|
||||
|
||||
void Rebuild(ID3D11Device *dev);
|
||||
|
||||
inline void Release() { query_disjoint.Release(); }
|
||||
|
||||
gs_timer_range(gs_device_t *device);
|
||||
};
|
||||
|
||||
struct gs_texture : gs_obj {
|
||||
gs_texture_type type;
|
||||
uint32_t levels;
|
||||
|
Reference in New Issue
Block a user