mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 20:58:31 +09:00
[Feat] (Diligent): wire CPU timer query fallback
- Add steady_clock based BeginTimeElapsedQuery/EndTimeElapsedQuery/QueryCounterTimestamp - Wire IsTimerQuerySupported/IsQueryResultAvailable/GetQueryResult64/DeleteBackendQuery - Update handoff; 16 Diligent tests pass
This commit is contained in:
+2
-1
@@ -161,6 +161,7 @@ Verified locally on Turnip Adreno 750:
|
||||
- `GenerateMipmap` (Diligent GPU mip generation on state textures)
|
||||
- `GetTexImage` / `GetTextureImage` (RGBA8 readback)
|
||||
- Fence sync entries (`FenceSync` / `ClientWaitSync` / `WaitSync` / `DeleteSync` / `GetSyncStatus`) as CPU always-signaled fallback
|
||||
- Timer query entries (`BeginTimeElapsedQuery` / `EndTimeElapsedQuery` / `QueryCounterTimestamp` / `GetQueryResult64` etc.) as CPU `steady_clock` fallback
|
||||
- `ReadPixels` from default and user color attachments
|
||||
- Primitive expansion:
|
||||
- `GL_TRIANGLE_FAN` expanded to triangle list
|
||||
@@ -219,7 +220,7 @@ Notes:
|
||||
- Textures auto-sync `ITextureObject` → Diligent resources, including mip levels and sampler state; compressed textures and integer/3-channel formats that Diligent lacks are still skipped.
|
||||
- Global UBO (default-block `glUniform*`) and named application UBO blocks (through `glBindBufferBase`/`glUniformBlockBinding`) now upload and bind; SSBOs are still not fed from frontend buffer bindings.
|
||||
- No swapchain / EGL window surface presentation yet; `Present()` only flushes.
|
||||
- No transform feedback / GPU queries / non-color readback; fence sync is provided as a CPU always-signaled fallback.
|
||||
- No transform feedback / GPU-accelerated queries / non-color readback; fence sync and timer queries use CPU fallbacks.
|
||||
- Draw range, multi-draw, instanced-draw wrappers, clear-buffer, blit, read-pixels, CopyTexImage*, CopyImageSubData, GenerateMipmap, GetTexImage/GetTextureImage and indirect draws are now wired; buffer subdata paths still remain.
|
||||
- A last-PSO cache now avoids recreating the pipeline when program/render-state/topology/VAO layout is unchanged; texture/UBO resources are still rebound dynamically per draw.
|
||||
- The `GLFunctionsTable` is only partially populated.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <DeviceContext.h>
|
||||
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
|
||||
namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
namespace {
|
||||
@@ -50,6 +51,12 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
Uint32 BaseInstance = 0;
|
||||
};
|
||||
|
||||
struct CpuTimerQuery {
|
||||
std::chrono::steady_clock::time_point Start;
|
||||
Uint64 TimestampNs = 0;
|
||||
Bool Available = false;
|
||||
};
|
||||
|
||||
const Uint8* ResolveIndirectCommandBytes(const void* indirect, SizeT requiredBytes, const char* label) {
|
||||
auto drawBuffer = MG_State::pGLContext->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (drawBuffer) {
|
||||
@@ -571,6 +578,57 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
}
|
||||
}
|
||||
|
||||
Bool IsTimerQuerySupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
BackendQueryHandle BeginTimeElapsedQuery() {
|
||||
auto* query = new CpuTimerQuery;
|
||||
query->Start = std::chrono::steady_clock::now();
|
||||
query->Available = false;
|
||||
return query;
|
||||
}
|
||||
|
||||
void EndTimeElapsedQuery(BackendQueryHandle query) {
|
||||
if (query == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto* cpuQuery = static_cast<CpuTimerQuery*>(query);
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
cpuQuery->TimestampNs = static_cast<Uint64>(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(now - cpuQuery->Start).count());
|
||||
cpuQuery->Available = true;
|
||||
}
|
||||
|
||||
BackendQueryHandle QueryCounterTimestamp() {
|
||||
auto* query = new CpuTimerQuery;
|
||||
query->TimestampNs = static_cast<Uint64>(
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch()).count());
|
||||
query->Available = true;
|
||||
return query;
|
||||
}
|
||||
|
||||
Bool IsQueryResultAvailable(BackendQueryHandle query) {
|
||||
return query != nullptr && static_cast<CpuTimerQuery*>(query)->Available;
|
||||
}
|
||||
|
||||
Bool GetQueryResult64(BackendQueryHandle query, Bool wait, Uint64* outNanoseconds) {
|
||||
if (query == nullptr || outNanoseconds == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto* cpuQuery = static_cast<CpuTimerQuery*>(query);
|
||||
if (!cpuQuery->Available && !wait) {
|
||||
return false;
|
||||
}
|
||||
*outNanoseconds = cpuQuery->TimestampNs;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeleteBackendQuery(BackendQueryHandle query) {
|
||||
delete static_cast<CpuTimerQuery*>(query);
|
||||
}
|
||||
|
||||
BackendSyncHandle FenceSync() {
|
||||
// CPU fallback fence: always signaled is a valid implementation for a
|
||||
// backend without native sync primitives. The handle still round-trips
|
||||
@@ -724,6 +782,13 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
m_functions.GL.WaitSync = WaitSync;
|
||||
m_functions.GL.DeleteSync = DeleteSync;
|
||||
m_functions.GL.GetSyncStatus = GetSyncStatus;
|
||||
m_functions.GL.IsTimerQuerySupported = IsTimerQuerySupported;
|
||||
m_functions.GL.BeginTimeElapsedQuery = BeginTimeElapsedQuery;
|
||||
m_functions.GL.EndTimeElapsedQuery = EndTimeElapsedQuery;
|
||||
m_functions.GL.QueryCounterTimestamp = QueryCounterTimestamp;
|
||||
m_functions.GL.IsQueryResultAvailable = IsQueryResultAvailable;
|
||||
m_functions.GL.GetQueryResult64 = GetQueryResult64;
|
||||
m_functions.GL.DeleteBackendQuery = DeleteBackendQuery;
|
||||
m_functions.Present = Present;
|
||||
|
||||
m_initialized = true;
|
||||
|
||||
Reference in New Issue
Block a user