mirror of
https://github.com/lucannez64/darling-lol.git
synced 2026-10-26 19:47:42 +00:00
Use optimal tiling for the drawable GL import on NVIDIA
NVIDIA's GL rejects GL_LINEAR_TILING_EXT with GL_INVALID_VALUE, so the linear internal image could not be imported and the window stayed black. Pick the tiling by GL_VENDOR; other drivers keep linear. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
1 parent
0b555fa54d
commit
6d5d04ff71
2 files changed
+43
-13
No files matched your search
@@ -212,11 +212,11 @@ Resources only the GPU uses (`private`, `memoryless`, and drawables, including L
|
|||||||
The first import of a drawable into the presenting OpenGL context, and the first semaphore import, are logged too; later ones only when they fail (at most five):
|
The first import of a drawable into the presenting OpenGL context, and the first semaphore import, are logged too; later ones only when they fail (at most five):
|
||||||
|
|
||||||
```
|
```
|
||||||
[MetalDevice] pid=… drawable GL import (first) dedicated=yes size=… 1920x1080 memoryType=1 tiling=linear glTiling=linear dedicated_error=0x0 import_error=0x0 setup_error=0x0 storage_error=0x0 query_error=0x0 ok
|
[MetalDevice] pid=… drawable GL import (first) dedicated=yes size=… 1920x1080 memoryType=1 vkTiling=linear glTiling=linear dedicated_error=0x0 import_error=0x0 setup_error=0x0 storage_error=0x0 query_error=0x0 ok
|
||||||
[MetalDevice] pid=… drawable GL semaphore (first) import_error=0x0 wait_error=0x0 ok (checked for the first 600 imports)
|
[MetalDevice] pid=… drawable GL semaphore (first) import_error=0x0 wait_error=0x0 ok (checked for the first 600 imports)
|
||||||
```
|
```
|
||||||
|
|
||||||
A non-zero error or `FAILED` means the frames cannot reach the window. Before 2026-10-16 the import did not mark the memory as dedicated, which the extension requires; Mesa ignores it, and it is the suspected cause of the NVIDIA black screen (not yet confirmed). If the game shows a black screen on NVIDIA, report it with this file.
|
A non-zero error or `FAILED` means the frames cannot reach the window. Before 2026-10-16 the import did not mark the memory as dedicated, which the extension requires; Mesa ignores it, and it is the suspected cause of the NVIDIA black screen (not yet confirmed). An NVIDIA log of 2026-10-16 showed `glTiling=optimal` with `setup_error=0x501 storage_error=0x501 FAILED`: NVIDIA's GL rejects `GL_LINEAR_TILING_EXT`, so the linear Vulkan image could not be imported. Since then the internal image and the GL texture use optimal tiling when `GL_VENDOR` contains NVIDIA (`vkTiling=optimal glTiling=optimal ok` is the expected line); everything else keeps linear. If the game shows a black screen on NVIDIA, report it with this file.
|
||||||
|
|
||||||
### Host-side checks
|
### Host-side checks
|
||||||
|
|
||||||
|
|||||||
+41
-11
@@ -7131,7 +7131,7 @@ index 5ad375f8..c8e83814 100644
|
|||||||
+- (BOOL) _treeHasAnimations;
|
+- (BOOL) _treeHasAnimations;
|
||||||
@end
|
@end
|
||||||
diff --git a/QuartzCore/CAMetalDrawable.mm b/QuartzCore/CAMetalDrawable.mm
|
diff --git a/QuartzCore/CAMetalDrawable.mm b/QuartzCore/CAMetalDrawable.mm
|
||||||
index d6f86b31..20e4e88b 100644
|
index d6f86b31..687f05d5 100644
|
||||||
--- a/QuartzCore/CAMetalDrawable.mm
|
--- a/QuartzCore/CAMetalDrawable.mm
|
||||||
+++ b/QuartzCore/CAMetalDrawable.mm
|
+++ b/QuartzCore/CAMetalDrawable.mm
|
||||||
@@ -31,6 +31,13 @@
|
@@ -31,6 +31,13 @@
|
||||||
@@ -7148,7 +7148,7 @@ index d6f86b31..20e4e88b 100644
|
|||||||
namespace DynamicVK = Indium::DynamicVK;
|
namespace DynamicVK = Indium::DynamicVK;
|
||||||
|
|
||||||
static void reportGLErrors(void) {
|
static void reportGLErrors(void) {
|
||||||
@@ -50,8 +57,98 @@ static void reportGLErrors(void) {
|
@@ -50,8 +57,111 @@ static void reportGLErrors(void) {
|
||||||
namespace Indium::DynamicVK {
|
namespace Indium::DynamicVK {
|
||||||
static DynamicFunction<PFN_vkGetSemaphoreFdKHR> vkGetSemaphoreFdKHR("vkGetSemaphoreFdKHR");
|
static DynamicFunction<PFN_vkGetSemaphoreFdKHR> vkGetSemaphoreFdKHR("vkGetSemaphoreFdKHR");
|
||||||
static DynamicFunction<PFN_vkGetMemoryFdKHR> vkGetMemoryFdKHR("vkGetMemoryFdKHR");
|
static DynamicFunction<PFN_vkGetMemoryFdKHR> vkGetMemoryFdKHR("vkGetMemoryFdKHR");
|
||||||
@@ -7243,11 +7243,24 @@ index d6f86b31..20e4e88b 100644
|
|||||||
+ appendDeviceLog(line);
|
+ appendDeviceLog(line);
|
||||||
+ });
|
+ });
|
||||||
+}
|
+}
|
||||||
|
+
|
||||||
|
+// The internal image is shared with OpenGL as linear memory because of a Mesa bug with
|
||||||
|
+// optimal tiling on AMD. NVIDIA's proprietary GL rejects GL_LINEAR_TILING_EXT
|
||||||
|
+// (GL_INVALID_VALUE), leaving the texture optimal and its storage import failing, which
|
||||||
|
+// shows as a black window. Only NVIDIA's own driver takes the optimal path; the check
|
||||||
|
+// runs once, with the presenting GL context current.
|
||||||
|
+static bool interopUsesLinearTiling() {
|
||||||
|
+ static const bool linear = []() {
|
||||||
|
+ const GLubyte* vendor = glGetString(GL_VENDOR);
|
||||||
|
+ return !(vendor && strstr(reinterpret_cast<const char*>(vendor), "NVIDIA"));
|
||||||
|
+ }();
|
||||||
|
+ return linear;
|
||||||
|
+}
|
||||||
+
|
+
|
||||||
//
|
//
|
||||||
// helper classes
|
// helper classes
|
||||||
//
|
//
|
||||||
@@ -129,27 +226,109 @@ public:
|
@@ -129,27 +239,109 @@ public:
|
||||||
// texture
|
// texture
|
||||||
//
|
//
|
||||||
|
|
||||||
@@ -7367,7 +7380,7 @@ index d6f86b31..20e4e88b 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
return targetIndex;
|
return targetIndex;
|
||||||
@@ -161,6 +340,11 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
@@ -161,6 +353,11 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
||||||
_pixelFormat(pixelFormat),
|
_pixelFormat(pixelFormat),
|
||||||
_framebufferOnly(framebufferOnly)
|
_framebufferOnly(framebufferOnly)
|
||||||
{
|
{
|
||||||
@@ -7379,7 +7392,16 @@ index d6f86b31..20e4e88b 100644
|
|||||||
//
|
//
|
||||||
// create the images
|
// create the images
|
||||||
//
|
//
|
||||||
@@ -219,7 +403,7 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
@@ -195,7 +392,7 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
||||||
|
// some drivers (e.g. AMD's drivers) don't play nice when sharing
|
||||||
|
// Vulkan images and OpenGL textures with optimal tiling
|
||||||
|
// (https://gitlab.freedesktop.org/mesa/mesa/-/issues/7657)
|
||||||
|
- imgInfo.tiling = VK_IMAGE_TILING_LINEAR;
|
||||||
|
+ imgInfo.tiling = interopUsesLinearTiling() ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
|
||||||
|
VkExternalMemoryImageCreateInfo extMemInfo {};
|
||||||
|
|
||||||
|
@@ -219,7 +416,7 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
||||||
|
|
||||||
DynamicVK::vkGetImageMemoryRequirements(_device->device(), _image, &reqs);
|
DynamicVK::vkGetImageMemoryRequirements(_device->device(), _image, &reqs);
|
||||||
|
|
||||||
@@ -7388,7 +7410,7 @@ index d6f86b31..20e4e88b 100644
|
|||||||
|
|
||||||
if (targetIndex == SIZE_MAX) {
|
if (targetIndex == SIZE_MAX) {
|
||||||
throw std::runtime_error("No suitable memory region found for image");
|
throw std::runtime_error("No suitable memory region found for image");
|
||||||
@@ -242,7 +426,7 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
@@ -242,7 +439,7 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
||||||
|
|
||||||
DynamicVK::vkGetImageMemoryRequirements(_device->device(), _internalImage, &reqs);
|
DynamicVK::vkGetImageMemoryRequirements(_device->device(), _internalImage, &reqs);
|
||||||
|
|
||||||
@@ -7397,7 +7419,7 @@ index d6f86b31..20e4e88b 100644
|
|||||||
|
|
||||||
if (targetIndex == SIZE_MAX) {
|
if (targetIndex == SIZE_MAX) {
|
||||||
throw std::runtime_error("No suitable memory region found for internal image");
|
throw std::runtime_error("No suitable memory region found for internal image");
|
||||||
@@ -380,16 +564,26 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
@@ -380,31 +577,70 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7426,7 +7448,14 @@ index d6f86b31..20e4e88b 100644
|
|||||||
|
|
||||||
GLint prevTex = 0;
|
GLint prevTex = 0;
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &prevTex);
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &prevTex);
|
||||||
@@ -401,10 +595,36 @@ CAMetalDrawableTexture::CAMetalDrawableTexture(CGSize size, Indium::PixelFormat
|
|
||||||
|
glCreateTextures(GL_TEXTURE_2D, 1, &_textureID);
|
||||||
|
reportGLErrors();
|
||||||
|
- glTextureParameteri(_textureID, GL_TEXTURE_TILING_EXT, GL_LINEAR_TILING_EXT /*GL_OPTIMAL_TILING_EXT*/);
|
||||||
|
+ if (interopUsesLinearTiling()) {
|
||||||
|
+ glTextureParameteri(_textureID, GL_TEXTURE_TILING_EXT, GL_LINEAR_TILING_EXT);
|
||||||
|
+ }
|
||||||
|
glTextureParameteri(_textureID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTextureParameteri(_textureID, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTextureParameteri(_textureID, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTextureParameteri(_textureID, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTextureParameteri(_textureID, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
glTextureParameteri(_textureID, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTextureParameteri(_textureID, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
@@ -7454,10 +7483,11 @@ index d6f86b31..20e4e88b 100644
|
|||||||
+ glGetTextureParameteriv(_textureID, GL_TEXTURE_TILING_EXT, &tiling);
|
+ glGetTextureParameteriv(_textureID, GL_TEXTURE_TILING_EXT, &tiling);
|
||||||
+ const GLenum queryError = glGetError();
|
+ const GLenum queryError = glGetError();
|
||||||
+ char line[512];
|
+ char line[512];
|
||||||
+ snprintf(line, sizeof(line), "drawable GL import%s dedicated=%s size=%llu %dx%d memoryType=%zu tiling=linear glTiling=%s"
|
+ snprintf(line, sizeof(line), "drawable GL import%s dedicated=%s size=%llu %dx%d memoryType=%zu vkTiling=%s glTiling=%s"
|
||||||
+ " dedicated_error=0x%x import_error=0x%x setup_error=0x%x storage_error=0x%x query_error=0x%x%s",
|
+ " dedicated_error=0x%x import_error=0x%x setup_error=0x%x storage_error=0x%x query_error=0x%x%s",
|
||||||
+ first ? " (first)" : "", dedicatedReadBack == GL_TRUE ? "yes" : (dedicatedReadBack == -1 ? "unknown" : "no"),
|
+ first ? " (first)" : "", dedicatedReadBack == GL_TRUE ? "yes" : (dedicatedReadBack == -1 ? "unknown" : "no"),
|
||||||
+ (unsigned long long) reqs.size, (int) _size.width, (int) _size.height, targetIndex,
|
+ (unsigned long long) reqs.size, (int) _size.width, (int) _size.height, targetIndex,
|
||||||
|
+ interopUsesLinearTiling() ? "linear" : "optimal",
|
||||||
+ tiling == GL_LINEAR_TILING_EXT ? "linear" : (tiling == GL_OPTIMAL_TILING_EXT ? "optimal" : "unknown"),
|
+ tiling == GL_LINEAR_TILING_EXT ? "linear" : (tiling == GL_OPTIMAL_TILING_EXT ? "optimal" : "unknown"),
|
||||||
+ dedicatedError, importError, setupError, storageError, queryError, failed ? " FAILED" : " ok");
|
+ dedicatedError, importError, setupError, storageError, queryError, failed ? " FAILED" : " ok");
|
||||||
+ appendDeviceLog(line);
|
+ appendDeviceLog(line);
|
||||||
@@ -7465,7 +7495,7 @@ index d6f86b31..20e4e88b 100644
|
|||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, prevTex);
|
glBindTexture(GL_TEXTURE_2D, prevTex);
|
||||||
};
|
};
|
||||||
@@ -605,35 +825,16 @@ void CAMetalDrawableActual::present() {
|
@@ -605,35 +841,16 @@ void CAMetalDrawableActual::present() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7507,7 +7537,7 @@ index d6f86b31..20e4e88b 100644
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,9 +903,46 @@ void CAMetalDrawableActual::reset() {
|
@@ -702,9 +919,46 @@ void CAMetalDrawableActual::reset() {
|
||||||
};
|
};
|
||||||
|
|
||||||
void CAMetalDrawableActual::synchronizeRender() {
|
void CAMetalDrawableActual::synchronizeRender() {
|
||||||
|
|||||||
Reference in new issue
Block a user