diff --git a/android/filament-android/src/main/cpp/Texture.cpp b/android/filament-android/src/main/cpp/Texture.cpp
index cac8d94d87..ea12b66b67 100644
--- a/android/filament-android/src/main/cpp/Texture.cpp
+++ b/android/filament-android/src/main/cpp/Texture.cpp
@@ -68,6 +68,21 @@ Java_com_google_android_filament_Texture_nIsTextureSwizzleSupported(JNIEnv*, jcl
return (jboolean) Texture::isTextureSwizzleSupported(*engine);
}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_com_google_android_filament_Texture_nGetMaxTextureSize(JNIEnv *, jclass,
+ jlong nativeEngine, jint sampler) {
+ Engine *engine = (Engine *) nativeEngine;
+ return Texture::getMaxTextureSize(*engine, (Texture::Sampler)sampler);
+}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_com_google_android_filament_Texture_nGetMaxArrayTextureLayers(JNIEnv *, jclass,
+ jlong nativeEngine) {
+ Engine *engine = (Engine *) nativeEngine;
+ return Texture::getMaxArrayTextureLayers(*engine);
+}
+
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Texture_nValidatePixelFormatAndType(JNIEnv*, jclass,
jint internalFormat, jint pixelDataFormat, jint pixelDataType) {
diff --git a/android/filament-android/src/main/java/com/google/android/filament/Texture.java b/android/filament-android/src/main/java/com/google/android/filament/Texture.java
index 15f7c72b7e..d62386e489 100644
--- a/android/filament-android/src/main/java/com/google/android/filament/Texture.java
+++ b/android/filament-android/src/main/java/com/google/android/filament/Texture.java
@@ -691,6 +691,24 @@ public class Texture {
pixelDataType.ordinal());
}
+ /**
+ * @param engine {@link Engine}
+ * @param type Texture sampler type
+ * @return The maximum size in texels of a texture of type \p type. At least 2048 for
+ * 2D textures, 256 for 3D textures
+ */
+ public static int getMaxTextureSize(@NonNull Engine engine, Sampler type) {
+ return nGetMaxTextureSize(engine.getNativeObject(), type.ordinal());
+ }
+
+ /**
+ * @param engine {@link Engine}
+ * @return The maximum number of layers supported by texture arrays. At least 256.
+ */
+ public static int getMaxArrayTextureLayers(@NonNull Engine engine) {
+ return nGetMaxArrayTextureLayers(engine.getNativeObject());
+ }
+
/**
* Use Builder to construct a Texture object instance.
*/
@@ -1289,6 +1307,8 @@ public class Texture {
private static native boolean nIsTextureFormatSupported(long nativeEngine, int internalFormat);
private static native boolean nIsTextureFormatMipmappable(long nativeEngine, int internalFormat);
private static native boolean nIsTextureSwizzleSupported(long nativeEngine);
+ private static native int nGetMaxTextureSize(long nativeObject, int ordinal);
+ private static native int nGetMaxArrayTextureLayers(long nativeObject);
private static native boolean nValidatePixelFormatAndType(int internalFormat, int pixelDataFormat,
int pixelDataType);
diff --git a/filament/backend/include/private/backend/DriverAPI.inc b/filament/backend/include/private/backend/DriverAPI.inc
index f87d18b4f6..476ec1557d 100644
--- a/filament/backend/include/private/backend/DriverAPI.inc
+++ b/filament/backend/include/private/backend/DriverAPI.inc
@@ -362,6 +362,8 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isProtectedTexturesSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthClampSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxUniformBufferSize)
+DECL_DRIVER_API_SYNCHRONOUS_N(size_t, getMaxTextureSize, backend::SamplerType, target)
+DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxArrayTextureLayers)
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage2, backend::Platform::ExternalImageHandleRef, image)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage, void*, image)
diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm
index b2c9173ce7..1cb97d0ca3 100644
--- a/filament/backend/src/metal/MetalDriver.mm
+++ b/filament/backend/src/metal/MetalDriver.mm
@@ -1177,6 +1177,16 @@ size_t MetalDriver::getMaxUniformBufferSize() {
return 256 * 1024 * 1024; // TODO: return the actual size instead of hardcoding the minspec
}
+size_t MetalDriver::getMaxTextureSize(SamplerType) {
+ // TODO: return the actual size instead of hardcoding the minspec
+ return 2048;
+}
+
+size_t MetalDriver::getMaxArrayTextureLayers() {
+ // TODO: return the actual size instead of hardcoding the minspec
+ return 256;
+}
+
void MetalDriver::updateIndexBuffer(Handle ibh, BufferDescriptor&& data,
uint32_t byteOffset) {
FILAMENT_CHECK_PRECONDITION(data.buffer)
diff --git a/filament/backend/src/noop/NoopDriver.cpp b/filament/backend/src/noop/NoopDriver.cpp
index 88b42a48a4..f78a8fa87a 100644
--- a/filament/backend/src/noop/NoopDriver.cpp
+++ b/filament/backend/src/noop/NoopDriver.cpp
@@ -240,6 +240,14 @@ size_t NoopDriver::getMaxUniformBufferSize() {
return 16384u;
}
+size_t NoopDriver::getMaxTextureSize(SamplerType target) {
+ return 2048u;
+}
+
+size_t NoopDriver::getMaxArrayTextureLayers() {
+ return 256u;
+}
+
void NoopDriver::updateIndexBuffer(Handle ibh, BufferDescriptor&& p,
uint32_t byteOffset) {
scheduleDestroy(std::move(p));
diff --git a/filament/backend/src/opengl/OpenGLContext.cpp b/filament/backend/src/opengl/OpenGLContext.cpp
index f652d92659..6e121f3f00 100644
--- a/filament/backend/src/opengl/OpenGLContext.cpp
+++ b/filament/backend/src/opengl/OpenGLContext.cpp
@@ -94,18 +94,22 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
}
#endif
- OpenGLContext::initExtensions(&ext, state.major, state.minor);
+ initExtensions(&ext, state.major, state.minor);
- OpenGLContext::initProcs(&procs, ext, state.major, state.minor);
+ initProcs(&procs, ext, state.major, state.minor);
- OpenGLContext::initBugs(&bugs, ext, state.major, state.minor,
+ initBugs(&bugs, ext, state.major, state.minor,
state.vendor, state.renderer, state.version, state.shader);
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &gets.max_renderbuffer_size);
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &gets.max_texture_image_units);
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &gets.max_combined_texture_image_units);
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gets.max_texture_size);
+ glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &gets.max_cubemap_texture_size);
+ glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &gets.max_3d_texture_size);
+ glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &gets.max_array_texture_layers);
- mFeatureLevel = OpenGLContext::resolveFeatureLevel(state.major, state.minor, ext, gets, bugs);
+ mFeatureLevel = resolveFeatureLevel(state.major, state.minor, ext, gets, bugs);
#ifdef BACKEND_OPENGL_VERSION_GLES
mShaderModel = ShaderModel::MOBILE;
@@ -177,6 +181,14 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
<< gets.max_anisotropy << '\n'
<< "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = "
<< gets.max_combined_texture_image_units << '\n'
+ << "GL_MAX_TEXTURE_SIZE = "
+ << gets.max_texture_size << '\n'
+ << "GL_MAX_CUBE_MAP_TEXTURE_SIZE = "
+ << gets.max_cubemap_texture_size << '\n'
+ << "GL_MAX_3D_TEXTURE_SIZE = "
+ << gets.max_3d_texture_size << '\n'
+ << "GL_MAX_ARRAY_TEXTURE_LAYERS = "
+ << gets.max_array_texture_layers << '\n'
<< "GL_MAX_DRAW_BUFFERS = "
<< gets.max_draw_buffers << '\n'
<< "GL_MAX_RENDERBUFFER_SIZE = "
diff --git a/filament/backend/src/opengl/OpenGLContext.h b/filament/backend/src/opengl/OpenGLContext.h
index 72e3f8f2b1..e83469c5ab 100644
--- a/filament/backend/src/opengl/OpenGLContext.h
+++ b/filament/backend/src/opengl/OpenGLContext.h
@@ -203,6 +203,10 @@ public:
GLint max_renderbuffer_size;
GLint max_samples;
GLint max_texture_image_units;
+ GLint max_texture_size;
+ GLint max_cubemap_texture_size;
+ GLint max_3d_texture_size;
+ GLint max_array_texture_layers;
GLint max_transform_feedback_separate_attribs;
GLint max_uniform_block_size;
GLint max_uniform_buffer_bindings;
diff --git a/filament/backend/src/opengl/OpenGLDriver.cpp b/filament/backend/src/opengl/OpenGLDriver.cpp
index 326a84b76b..9500c124c7 100644
--- a/filament/backend/src/opengl/OpenGLDriver.cpp
+++ b/filament/backend/src/opengl/OpenGLDriver.cpp
@@ -2460,6 +2460,26 @@ size_t OpenGLDriver::getMaxUniformBufferSize() {
return mContext.gets.max_uniform_block_size;
}
+size_t OpenGLDriver::getMaxTextureSize(SamplerType target) {
+ switch (target) {
+ case SamplerType::SAMPLER_2D:
+ case SamplerType::SAMPLER_2D_ARRAY:
+ case SamplerType::SAMPLER_EXTERNAL:
+ return mContext.gets.max_texture_size;
+ case SamplerType::SAMPLER_CUBEMAP:
+ return mContext.gets.max_cubemap_texture_size;
+ case SamplerType::SAMPLER_3D:
+ return mContext.gets.max_3d_texture_size;
+ case SamplerType::SAMPLER_CUBEMAP_ARRAY:
+ return mContext.gets.max_cubemap_texture_size;
+ }
+ return 0;
+}
+
+size_t OpenGLDriver::getMaxArrayTextureLayers() {
+ return mContext.gets.max_array_texture_layers;
+}
+
// ------------------------------------------------------------------------------------------------
// Swap chains
// ------------------------------------------------------------------------------------------------
diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp
index 7958c67def..e386b92421 100644
--- a/filament/backend/src/vulkan/VulkanDriver.cpp
+++ b/filament/backend/src/vulkan/VulkanDriver.cpp
@@ -1130,6 +1130,16 @@ size_t VulkanDriver::getMaxUniformBufferSize() {
return 32768;
}
+size_t VulkanDriver::getMaxTextureSize(SamplerType) {
+ // TODO: return the actual size instead of hardcoded value
+ return 2048;
+}
+
+size_t VulkanDriver::getMaxArrayTextureLayers() {
+ // TODO: return the actual size instead of hardcoded value
+ return 256;
+}
+
void VulkanDriver::setVertexBufferObject(Handle vbh, uint32_t index,
Handle boh) {
auto vb = resource_ptr::cast(&mResourceManager, vbh);
diff --git a/filament/backend/src/webgpu/WebGPUDriver.cpp b/filament/backend/src/webgpu/WebGPUDriver.cpp
index f399753dc5..c3eaeb7785 100644
--- a/filament/backend/src/webgpu/WebGPUDriver.cpp
+++ b/filament/backend/src/webgpu/WebGPUDriver.cpp
@@ -651,10 +651,18 @@ uint8_t WebGPUDriver::getMaxDrawBuffers() {
return MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT;
}
-size_t WebGPUDriver::getMaxUniformBufferSize() {
+size_t WebGPUDriver::getMaxUniformBufferSize(SamplerType) {
return 16384u;
}
+size_t WebGPUDriver::getMaxTextureSize() {
+ return 2048u;
+}
+
+size_t WebGPUDriver::getMaxArrayTextureLayers() {
+ return 256u;
+}
+
void WebGPUDriver::updateIndexBuffer(Handle ibh, BufferDescriptor&& p,
uint32_t byteOffset) {
scheduleDestroy(std::move(p));
diff --git a/filament/include/filament/Texture.h b/filament/include/filament/Texture.h
index caac008472..3241d9a932 100644
--- a/filament/include/filament/Texture.h
+++ b/filament/include/filament/Texture.h
@@ -106,6 +106,13 @@ public:
/** @return Whether a combination of texture format, pixel format and type is valid. */
static bool validatePixelFormatAndType(InternalFormat internalFormat, Format format, Type type) noexcept;
+ /** @return the maximum size in texels of a texture of type \p type. At least 2048 for
+ * 2D textures, 256 for 3D textures. */
+ static size_t getMaxTextureSize(Engine& engine, Sampler type) noexcept;
+
+ /** @return the maximum number of layers supported by texture arrays. At least 256. */
+ static size_t getMaxArrayTextureLayers(Engine& engine) noexcept;
+
/**
* Options for environment prefiltering into reflection map
*
diff --git a/filament/src/Texture.cpp b/filament/src/Texture.cpp
index 02086855a6..9b00f8322b 100644
--- a/filament/src/Texture.cpp
+++ b/filament/src/Texture.cpp
@@ -108,4 +108,12 @@ bool Texture::validatePixelFormatAndType(InternalFormat internalFormat, Format f
return FTexture::validatePixelFormatAndType(internalFormat, format, type);
}
+size_t Texture::getMaxTextureSize(Engine& engine, Sampler type) noexcept {
+ return FTexture::getMaxTextureSize(downcast(engine), type);
+
+}
+size_t Texture::getMaxArrayTextureLayers(Engine& engine) noexcept {
+ return FTexture::getMaxArrayTextureLayers(downcast(engine));
+}
+
} // namespace filament
diff --git a/filament/src/details/Texture.cpp b/filament/src/details/Texture.cpp
index 3749344d35..e9becb0ec7 100644
--- a/filament/src/details/Texture.cpp
+++ b/filament/src/details/Texture.cpp
@@ -164,6 +164,20 @@ Texture* Texture::Builder::build(Engine& engine) {
(isProtectedTexturesSupported && useProtectedMemory) || !useProtectedMemory)
<< "Texture is PROTECTED but protected textures are not supported";
+ size_t const maxTextureDimension = getMaxTextureSize(engine, mImpl->mTarget);
+ size_t const maxTextureDepth = (mImpl->mTarget == Sampler::SAMPLER_2D_ARRAY ||
+ mImpl->mTarget == Sampler::SAMPLER_CUBEMAP_ARRAY)
+ ? getMaxArrayTextureLayers(engine)
+ : maxTextureDimension;
+
+ FILAMENT_CHECK_PRECONDITION(
+ mImpl->mWidth <= maxTextureDimension &&
+ mImpl->mHeight <= maxTextureDimension &&
+ mImpl->mDepth <= maxTextureDepth) << "Texture dimensions out of range: "
+ << "width= " << mImpl->mWidth << " (>" << maxTextureDimension << ")"
+ <<", height= " << mImpl->mHeight << " (>" << maxTextureDimension << ")"
+ << ", depth= " << mImpl->mDepth << " (>" << maxTextureDepth << ")";
+
const auto validateSamplerType = [&engine = downcast(engine)](SamplerType const sampler) -> bool {
switch (sampler) {
case SamplerType::SAMPLER_2D:
@@ -672,6 +686,14 @@ bool FTexture::isTextureSwizzleSupported(FEngine& engine) noexcept {
return engine.getDriverApi().isTextureSwizzleSupported();
}
+size_t FTexture::getMaxTextureSize(FEngine& engine, Sampler type) noexcept {
+ return engine.getDriverApi().getMaxTextureSize(type);
+}
+
+size_t FTexture::getMaxArrayTextureLayers(FEngine& engine) noexcept {
+ return engine.getDriverApi().getMaxArrayTextureLayers();
+}
+
size_t FTexture::computeTextureDataSize(Format const format, Type const type,
size_t const stride, size_t const height, size_t const alignment) noexcept {
return PixelBufferDescriptor::computeDataSize(format, type, stride, height, alignment);
diff --git a/filament/src/details/Texture.h b/filament/src/details/Texture.h
index 7e463e7834..d5aa46bb4d 100644
--- a/filament/src/details/Texture.h
+++ b/filament/src/details/Texture.h
@@ -124,6 +124,10 @@ public:
static bool validatePixelFormatAndType(backend::TextureFormat internalFormat,
backend::PixelDataFormat format, backend::PixelDataType type) noexcept;
+ static size_t getMaxTextureSize(FEngine& engine, Sampler type) noexcept;
+
+ static size_t getMaxArrayTextureLayers(FEngine& engine) noexcept;
+
bool textureHandleCanMutate() const noexcept;
void updateLodRange(uint8_t level) noexcept;