Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 155 additions & 0 deletions include/SDL3/SDL_gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,20 @@ typedef struct SDL_GPUCopyPass SDL_GPUCopyPass;
*/
typedef struct SDL_GPUFence SDL_GPUFence;

/**
* An opaque handle representing a query pool.
*
* \since This struct is available since SDL 3.6.0.
*
* \sa SDL_CreateGPUQueryPool
* \sa SDL_ReleaseGPUQueryPool
* \sa SDL_BeginGPUQuery
* \sa SDL_EndGPUQuery
* \sa SDL_DownloadGPUQueryResults
* \sa SDL_GetGPUTimestampFrequency
*/
typedef struct SDL_GPUQueryPool SDL_GPUQueryPool;

/**
* Specifies the primitive topology of a graphics pipeline.
*
Expand Down Expand Up @@ -1370,6 +1384,20 @@ typedef enum SDL_GPUSwapchainComposition
SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2084
} SDL_GPUSwapchainComposition;

/**
* Specifies a kind of GPU Query.
*
* \since This enum is available since SDL 3.6.0.
*
* \sa SDL_CreateGPUQueryPool
*/
typedef enum SDL_GPUQueryType
{
SDL_GPU_QUERY_TIMESTAMP,
SDL_GPU_QUERY_BINARY_OCCLUSION,
SDL_GPU_QUERY_PRECISE_OCCLUSION
} SDL_GPUQueryType;

/* Structures */

/**
Expand Down Expand Up @@ -1816,6 +1844,21 @@ typedef struct SDL_GPUTransferBufferCreateInfo
SDL_PropertiesID props; /**< A properties ID for extensions. Should be 0 if no extensions are needed. */
} SDL_GPUTransferBufferCreateInfo;

/**
* A structure specifying the parameters of a query pool.
*
* \since This struct is available since SDL 3.6.0.
*
* \sa SDL_CreateGPUQueryPool
*/
typedef struct SDL_GPUQueryPoolCreateInfo
{
SDL_GPUQueryType type; /**< The type of query intended to be used by the client. */
Uint32 query_count; /**< The maximum number of queries in the pool. */

SDL_PropertiesID props; /**< A properties ID for extensions. Should be 0 if no extensions are needed. */
} SDL_GPUQueryPoolCreateInfo;

/* Pipeline state structures */

/**
Expand Down Expand Up @@ -4028,6 +4071,30 @@ extern SDL_DECLSPEC void SDLCALL SDL_DownloadFromGPUBuffer(
const SDL_GPUBufferRegion *source,
const SDL_GPUTransferBufferLocation *destination);

/**
* Copies results of a GPU query to a buffer.
*
* This data is not guaranteed to be copied until the command buffer fence is
* signaled.
*
* After this function is called, the data in the query pool is no longer valid,
* so don't call this function multiple times before performing another query.
Comment on lines +4080 to +4081
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this discard the entire contents of the query pool or just the data for [first_query, first_query + count]? It reads like the former

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That comment is actually wrong, I need to add an explicit reset function because Vulkan requires it.

*
* \param copy_pass a copy pass handle.
* \param pool a query pool handle.
* \param first_query starting index of the queries to copy.
* \param count the number of queries to copy.
* \param destination the destination buffer and offset.
*
* \since This struct is available since SDL 3.6.0.
*/
extern SDL_DECLSPEC void SDLCALL SDL_DownloadGPUQueryResults(
SDL_GPUCopyPass *copy_pass,
SDL_GPUQueryPool *pool,
Uint32 first_query,
Uint32 count,
SDL_GPUTransferBufferLocation *destination);

/**
* Ends the current copy pass.
*
Expand Down Expand Up @@ -4492,6 +4559,94 @@ extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGPUFence(
SDL_GPUDevice *device,
SDL_GPUFence *fence);

/**
* Gets GPU timestamp frequency.
*
* Use this to compute wall clock times from timestamps.
*
* \param device a GPU context.
* \returns the number of nanoseconds required for a timestamp query to be incremented by 1.
*
* \since This function is available since SDL 3.6.0.
*
* \sa SDL_CreateGPUQueryPool
*/
extern SDL_DECLSPEC float SDLCALL SDL_GetGPUTimestampFrequency(SDL_GPUDevice *device);

/**
* Creates a query pool object to be used in queries.
*
* \param device a GPU context.
* \param createinfo a struct describing the state of the pool to create.
* \returns a query pool object on success, or NULL on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.6.0.
*
* \sa SDL_GetGPUTimestampFrequency
* \sa SDL_BeginGPUQuery
* \sa SDL_EndGPUQuery
* \sa SDL_DownloadGPUQueryResults
* \sa SDL_ReleaseGPUQueryPool
*/
extern SDL_DECLSPEC SDL_GPUQueryPool * SDLCALL SDL_CreateGPUQueryPool(
SDL_GPUDevice *device,
SDL_GPUQueryPoolCreateInfo *createinfo);

/**
* Begins a query on a command buffer.
*
* For timestamp queries, this will produce a timestamp as soon as all previous commands are taken by the command queue.
* Note that this means for timestamp queries you should use a different index from the one you use in SDL_EndGPUQuery.
*
* \param command_buffer a command buffer.
* \param pool a query pool.
* \param index the index within the pool for the query.
*
* \since This function is available since SDL 3.6.0.
*
* \sa SDL_EndGPUQuery
*/
extern SDL_DECLSPEC void SDLCALL SDL_BeginGPUQuery(
SDL_GPUCommandBuffer *command_buffer,
SDL_GPUQueryPool *pool,
Uint32 index);

/**
* Ends a query on a command buffer.
*
* For timestamp queries, this will produce a timestamp as soon as all previous commands are finished in the command queue.
* Note that this means for timestamp queries you should use a different index from the one you used in SDL_BeginGPUQuery.
*
* \param command_buffer a command buffer.
* \param pool a query pool.
* \param index the index within the pool for the query.
*
* \since This function is available since SDL 3.6.0.
*
* \sa SDL_BeginGPUQuery
*/
extern SDL_DECLSPEC void SDLCALL SDL_EndGPUQuery(
SDL_GPUCommandBuffer *command_buffer,
SDL_GPUQueryPool *pool,
Uint32 index);

/**
* Frees the given query pool as soon as it is safe to do so.
*
* You must not reference the query pool after calling this function.
*
* \param device a GPU context.
* \param pool a query pool.
*
* \since This function is available since SDL 3.6.0.
*
* \sa SDL_CreateGPUQueryPool
*/
extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGPUQueryPool(
SDL_GPUDevice *device,
SDL_GPUQueryPool *pool);

/* Format Info */

/**
Expand Down
6 changes: 6 additions & 0 deletions src/dynapi/SDL_dynapi.exports
Original file line number Diff line number Diff line change
Expand Up @@ -1290,3 +1290,9 @@ _SDL_LoadJPG
_SDL_HasSVE2
_SDL_GamepadHasCapSense
_SDL_GetGamepadCapSense
_SDL_DownloadGPUQueryResults
_SDL_GetGPUTimestampFrequency
_SDL_CreateGPUQueryPool
_SDL_BeginGPUQuery
_SDL_EndGPUQuery
_SDL_ReleaseGPUQueryPool
6 changes: 6 additions & 0 deletions src/dynapi/SDL_dynapi.sym
Original file line number Diff line number Diff line change
Expand Up @@ -1291,6 +1291,12 @@ SDL3_0.0.0 {
SDL_HasSVE2;
SDL_GamepadHasCapSense;
SDL_GetGamepadCapSense;
SDL_DownloadGPUQueryResults;
SDL_GetGPUTimestampFrequency;
SDL_CreateGPUQueryPool;
SDL_BeginGPUQuery;
SDL_EndGPUQuery;
SDL_ReleaseGPUQueryPool;
# extra symbols go here (don't modify this line)
local: *;
};
6 changes: 6 additions & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -1317,3 +1317,9 @@
#define SDL_HasSVE2 SDL_HasSVE2_REAL
#define SDL_GamepadHasCapSense SDL_GamepadHasCapSense_REAL
#define SDL_GetGamepadCapSense SDL_GetGamepadCapSense_REAL
#define SDL_DownloadGPUQueryResults SDL_DownloadGPUQueryResults_REAL
#define SDL_GetGPUTimestampFrequency SDL_GetGPUTimestampFrequency_REAL
#define SDL_CreateGPUQueryPool SDL_CreateGPUQueryPool_REAL
#define SDL_BeginGPUQuery SDL_BeginGPUQuery_REAL
#define SDL_EndGPUQuery SDL_EndGPUQuery_REAL
#define SDL_ReleaseGPUQueryPool SDL_ReleaseGPUQueryPool_REAL
6 changes: 6 additions & 0 deletions src/dynapi/SDL_dynapi_procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1325,3 +1325,9 @@ SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadJPG,(const char *a),(a),return)
SDL_DYNAPI_PROC(bool,SDL_HasSVE2,(void),(),return)
SDL_DYNAPI_PROC(bool,SDL_GamepadHasCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return)
SDL_DYNAPI_PROC(bool,SDL_GetGamepadCapSense,(SDL_Gamepad *a,SDL_GamepadCapSenseType b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_DownloadGPUQueryResults,(SDL_GPUCopyPass *a,SDL_GPUQueryPool *b,Uint32 c,Uint32 d,SDL_GPUTransferBufferLocation *e),(a,b,c,d,e),)
SDL_DYNAPI_PROC(float,SDL_GetGPUTimestampFrequency,(SDL_GPUDevice *a),(a),return)
SDL_DYNAPI_PROC(SDL_GPUQueryPool*,SDL_CreateGPUQueryPool,(SDL_GPUDevice *a,SDL_GPUQueryPoolCreateInfo *b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_BeginGPUQuery,(SDL_GPUCommandBuffer *a,SDL_GPUQueryPool *b,Uint32 c),(a,b,c),)
SDL_DYNAPI_PROC(void,SDL_EndGPUQuery,(SDL_GPUCommandBuffer *a,SDL_GPUQueryPool *b,Uint32 c),(a,b,c),)
SDL_DYNAPI_PROC(void,SDL_ReleaseGPUQueryPool,(SDL_GPUDevice *a,SDL_GPUQueryPool *b),(a,b),)
110 changes: 110 additions & 0 deletions src/gpu/SDL_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3020,6 +3020,36 @@ void SDL_DownloadFromGPUBuffer(
destination);
}

void SDL_DownloadGPUQueryResults(
SDL_GPUCopyPass *copy_pass,
SDL_GPUQueryPool *pool,
Uint32 first_query,
Uint32 count,
SDL_GPUTransferBufferLocation *destination)
{
CHECK_PARAM(copy_pass == NULL) {
SDL_InvalidParamError("copy_pass");
return;
}

CHECK_PARAM(pool == NULL) {
SDL_InvalidParamError("pool");
return;
}

CHECK_PARAM(destination == NULL) {
SDL_InvalidParamError("destination");
return;
}

COPYPASS_DEVICE->DownloadQueryResults(
COPYPASS_COMMAND_BUFFER,
pool,
first_query,
count,
destination);
}

void SDL_EndGPUCopyPass(
SDL_GPUCopyPass *copy_pass)
{
Expand Down Expand Up @@ -3511,6 +3541,86 @@ void SDL_ReleaseGPUFence(
fence);
}

float SDL_GetGPUTimestampFrequency(SDL_GPUDevice *device)
{
CHECK_DEVICE_MAGIC(device, 0);

return device->GetTimestampFrequency(device->driverData);
}

SDL_GPUQueryPool *SDL_CreateGPUQueryPool(
SDL_GPUDevice *device,
SDL_GPUQueryPoolCreateInfo *createinfo)
{
CHECK_DEVICE_MAGIC(device, NULL);

CHECK_PARAM(createinfo == NULL) {
SDL_InvalidParamError("createinfo");
return NULL;
}

return device->CreateQueryPool(
device->driverData,
createinfo);
}

void SDL_BeginGPUQuery(
SDL_GPUCommandBuffer *command_buffer,
SDL_GPUQueryPool *pool,
Uint32 index)
{
CHECK_PARAM(command_buffer == NULL) {
SDL_InvalidParamError("command_buffer");
return;
}

CHECK_PARAM(pool == NULL) {
SDL_InvalidParamError("pool");
return;
}

COMMAND_BUFFER_DEVICE->BeginQuery(
command_buffer,
pool,
index);
}

void SDL_EndGPUQuery(
SDL_GPUCommandBuffer *command_buffer,
SDL_GPUQueryPool *pool,
Uint32 index)
{
CHECK_PARAM(command_buffer == NULL) {
SDL_InvalidParamError("command_buffer");
return;
}

CHECK_PARAM(pool == NULL) {
SDL_InvalidParamError("pool");
return;
}

COMMAND_BUFFER_DEVICE->EndQuery(
command_buffer,
pool,
index);
}

void SDL_ReleaseGPUQueryPool(
SDL_GPUDevice *device,
SDL_GPUQueryPool *pool)
{
CHECK_DEVICE_MAGIC(device, );

CHECK_PARAM(pool == NULL) {
return;
}

return device->ReleaseQueryPool(
device->driverData,
pool);
}

Uint32 SDL_CalculateGPUTextureFormatSize(
SDL_GPUTextureFormat format,
Uint32 width,
Expand Down
Loading
Loading