Browse Source

Merge branch '12.0' into Texture

Alex Szpakowski 5 years ago
parent
commit
024d9443a0
1 changed files with 32 additions and 3 deletions
  1. 32 3
      src/modules/graphics/opengl/StreamBuffer.cpp

+ 32 - 3
src/modules/graphics/opengl/StreamBuffer.cpp

@@ -406,7 +406,12 @@ public:
 		if (!alignedMalloc((void **) &data, alignedSize, alignment))
 			throw love::Exception("Out of memory.");
 
-		loadVolatile();
+		if (!loadVolatile())
+		{
+			ptrdiff_t pointer = (ptrdiff_t) data;
+			alignedFree(data);
+			throw love::Exception("AMD Pinned Memory StreamBuffer implementation failed to create buffer (address: %p, alignment: %ld, aiigned size: %ld)", pointer, alignment, alignedSize);
+		}
 	}
 
 	~StreamBufferPinnedMemory()
@@ -441,9 +446,19 @@ public:
 
 		glGenBuffers(1, &vbo);
 
+		while (glGetError() != GL_NO_ERROR)
+			/* Clear errors. */;
+
 		glBindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, vbo);
 		glBufferData(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, alignedSize, data, GL_STREAM_DRAW);
 
+		if (glGetError() != GL_NO_ERROR)
+		{
+			gl.deleteBuffer(vbo);
+			vbo = 0;
+			return false;
+		}
+
 		frameGPUReadOffset = 0;
 		frameIndex = 0;
 
@@ -485,8 +500,22 @@ love::graphics::StreamBuffer *CreateStreamBuffer(BufferType mode, size_t size)
 			// AMD's pinned memory seems to be faster than persistent mapping,
 			// on AMD GPUs.
 			if (GLAD_AMD_pinned_memory)
-				return new StreamBufferPinnedMemory(mode, size);
-			else if (GLAD_VERSION_4_4 || GLAD_ARB_buffer_storage)
+			{
+				try
+				{
+					return new StreamBufferPinnedMemory(mode, size);
+				}
+				catch (love::Exception &)
+				{
+					// According to the spec, pinned memory can fail if the RAM
+					// allocation can't be mapped to the GPU's address space.
+					// This seems to happen in practice on Mesa + amdgpu:
+					// https://bitbucket.org/rude/love/issues/1540
+					// Fall through to other implementations when that happens.
+				}
+			}
+
+			if (GLAD_VERSION_4_4 || GLAD_ARB_buffer_storage)
 				return new StreamBufferPersistentMapSync(mode, size);
 
 			// Most modern drivers have a separate internal thread which queues