From 6ea4a66451c8e79b9aa3a80097d35af9b3ed409c Mon Sep 17 00:00:00 2001
From: Evan Hemsley <[EMAIL REDACTED]>
Date: Thu, 10 Oct 2024 16:34:38 -0700
Subject: [PATCH] GPU: Add SDL_CalculateGPUTextureFormatSize (#11146)
---------
Co-authored-by: Sam Lantinga <slouken@libsdl.org>
---
include/SDL3/SDL_gpu.h | 17 +++++++++++++++++
src/dynapi/SDL_dynapi.sym | 1 +
src/dynapi/SDL_dynapi_overrides.h | 1 +
src/dynapi/SDL_dynapi_procs.h | 1 +
src/gpu/SDL_gpu.c | 13 +++++++++++++
src/gpu/SDL_sysgpu.h | 12 ------------
src/gpu/metal/SDL_gpu_metal.m | 2 +-
7 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h
index 66455d67b23b6..89d5000a299f4 100644
--- a/include/SDL3/SDL_gpu.h
+++ b/include/SDL3/SDL_gpu.h
@@ -3714,6 +3714,23 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GPUTextureSupportsSampleCount(
SDL_GPUTextureFormat format,
SDL_GPUSampleCount sample_count);
+/**
+ * Calculate the size in bytes of a texture format with dimensions.
+ *
+ * \param format a texture format.
+ * \param width width in pixels.
+ * \param height height in pixels.
+ * \param depth_or_layer_count depth for 3D textures or layer count otherwise.
+ * \returns the size of a texture with this format and dimensions.
+ *
+ * \since This function is available since SDL 3.1.5.
+ */
+extern SDL_DECLSPEC Uint32 SDLCALL SDL_CalculateGPUTextureFormatSize(
+ SDL_GPUTextureFormat format,
+ Uint32 width,
+ Uint32 height,
+ Uint32 depth_or_layer_count);
+
#ifdef SDL_PLATFORM_GDK
/**
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index c60e930c03666..06cc432a93f95 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -1178,6 +1178,7 @@ SDL3_0.0.0 {
SDL_wcstol;
SDL_StepBackUTF8;
SDL_DelayPrecise;
+ SDL_CalculateGPUTextureFormatSize;
# extra symbols go here (don't modify this line)
local: *;
};
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index c03a633f12739..6de3884830abf 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -1203,3 +1203,4 @@
#define SDL_wcstol SDL_wcstol_REAL
#define SDL_StepBackUTF8 SDL_StepBackUTF8_REAL
#define SDL_DelayPrecise SDL_DelayPrecise_REAL
+#define SDL_CalculateGPUTextureFormatSize SDL_CalculateGPUTextureFormatSize_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 59c32eaaf55b5..e6dcb8b8028ba 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -1209,3 +1209,4 @@ SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),r
SDL_DYNAPI_PROC(long,SDL_wcstol,(const wchar_t *a, wchar_t **b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(Uint32,SDL_StepBackUTF8,(const char *a, const char **b),(a,b),return)
SDL_DYNAPI_PROC(void,SDL_DelayPrecise,(Uint64 a),(a),)
+SDL_DYNAPI_PROC(Uint32,SDL_CalculateGPUTextureFormatSize,(SDL_GPUTextureFormat a, Uint32 b, Uint32 c, Uint32 d),(a,b,c,d),return)
diff --git a/src/gpu/SDL_gpu.c b/src/gpu/SDL_gpu.c
index 3607a7954063f..c550c7a5703d9 100644
--- a/src/gpu/SDL_gpu.c
+++ b/src/gpu/SDL_gpu.c
@@ -2796,3 +2796,16 @@ void SDL_ReleaseGPUFence(
device->driverData,
fence);
}
+
+Uint32 SDL_CalculateGPUTextureFormatSize(
+ SDL_GPUTextureFormat format,
+ Uint32 width,
+ Uint32 height,
+ Uint32 depth_or_layer_count)
+{
+ Uint32 blockWidth = Texture_GetBlockWidth(format);
+ Uint32 blockHeight = Texture_GetBlockHeight(format);
+ Uint32 blocksPerRow = (width + blockWidth - 1) / blockWidth;
+ Uint32 blocksPerColumn = (height + blockHeight - 1) / blockHeight;
+ return depth_or_layer_count * blocksPerRow * blocksPerColumn * SDL_GPUTextureFormatTexelBlockSize(format);
+}
diff --git a/src/gpu/SDL_sysgpu.h b/src/gpu/SDL_sysgpu.h
index f06ae62d677d0..51fd06fcc70ea 100644
--- a/src/gpu/SDL_sysgpu.h
+++ b/src/gpu/SDL_sysgpu.h
@@ -362,18 +362,6 @@ static inline Uint32 BytesPerRow(
return blocksPerRow * SDL_GPUTextureFormatTexelBlockSize(format);
}
-static inline Sint32 BytesPerImage(
- Uint32 width,
- Uint32 height,
- SDL_GPUTextureFormat format)
-{
- Uint32 blockWidth = Texture_GetBlockWidth(format);
- Uint32 blockHeight = Texture_GetBlockHeight(format);
- Uint32 blocksPerRow = (width + blockWidth - 1) / blockWidth;
- Uint32 blocksPerColumn = (height + blockHeight - 1) / blockHeight;
- return blocksPerRow * blocksPerColumn * SDL_GPUTextureFormatTexelBlockSize(format);
-}
-
// GraphicsDevice Limits
#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
diff --git a/src/gpu/metal/SDL_gpu_metal.m b/src/gpu/metal/SDL_gpu_metal.m
index faed52bb6156b..d60d69d4ba5b1 100644
--- a/src/gpu/metal/SDL_gpu_metal.m
+++ b/src/gpu/metal/SDL_gpu_metal.m
@@ -1752,7 +1752,7 @@ static void METAL_UploadToTexture(
copyFromBuffer:bufferContainer->activeBuffer->handle
sourceOffset:source->offset
sourceBytesPerRow:BytesPerRow(destination->w, textureContainer->header.info.format)
- sourceBytesPerImage:BytesPerImage(destination->w, destination->h, textureContainer->header.info.format)
+ sourceBytesPerImage:SDL_CalculateGPUTextureFormatSize(textureContainer->header.info.format, destination->w, destination->h, destination->d)
sourceSize:MTLSizeMake(destination->w, destination->h, destination->d)
toTexture:metalTexture->handle
destinationSlice:destination->layer