Prechádzať zdrojové kódy

some corrections. glSyncFence still failing...

Zoadian 11 rokov pred
rodič
commit
d9a0d5b8cd
2 zmenil súbory, kde vykonal 108 pridanie a 103 odobranie
  1. 76 77
      source/gl/renderer.d
  2. 32 26
      source/gl/sync.d

+ 76 - 77
source/gl/renderer.d

@@ -21,7 +21,6 @@ enum maxIndices = 1 * 1024 * 1024;
 enum maxPerInstanceParams = 1 * 1024 * 1024;
 enum maxIndirectCommands = 1 * 1024 * 1024;
 enum bufferCount = 3; //tripple buffering
-enum kOneSecondInNanoSeconds = GLuint64(1000000000);
 
 
 
@@ -214,15 +213,15 @@ struct Renderer {
 	GlArrayBuffer!VertexData vertexBuffer; // vertex data for all meshes
 	GlElementArrayBuffer!IndexData indexBuffer; //index data for all meshes
 	GlShaderStorageBuffer!GlDrawParameter perInstanceParamBuffer; // is filled with draw parameters for each instance each frame. shall be accessed as a ringbuffer
-	GlDrawIndirectBuffer!GlDrawElementsIndirectCommand dispatchIndirectCommandBuffer; // is filled with DrawElementsIndirectCommand for each mesh each frame. shall be accessed as a ringbuffer
+	GlDrawIndirectBuffer!GlDrawElementsIndirectCommand drawIndirectCommandBuffer; // is filled with DrawElementsIndirectCommand for each mesh each frame. shall be accessed as a ringbuffer
 	GlSyncManager vertexSyncManager;
 	GlSyncManager indexSyncManager;
 	GlSyncManager perInstanceParamSyncManager;
-	GlSyncManager dispatchIndirectCommandSyncManager;
+	GlSyncManager drawIndirectCommandSyncManager;
 	size_t vertexRingbufferIndex = 0;
 	size_t indexRingbufferIndex = 0;
 	size_t perInstanceParamRingbufferIndex = 0;
-	size_t dispatchIndirectCommandRingbufferIndex = 0;
+	size_t drawIndirectCommandRingbufferIndex = 0;
 	
 	void construct(uint width, uint height) {
 		GLbitfield createFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;//TODO: ?? | GL_MAP_DYNAMIC_STORAGE_BIT;
@@ -233,11 +232,11 @@ struct Renderer {
 		this.vertexBuffer.construct(bufferCount * maxVertices, createFlags, mapFlags);
 		this.indexBuffer.construct(bufferCount * maxIndices, createFlags, mapFlags);
 		this.perInstanceParamBuffer.construct(bufferCount * maxPerInstanceParams, createFlags, mapFlags);
-		this.dispatchIndirectCommandBuffer.construct(bufferCount * maxIndirectCommands, createFlags, mapFlags);
+		this.drawIndirectCommandBuffer.construct(bufferCount * maxIndirectCommands, createFlags, mapFlags);
 		this.vertexSyncManager.construct();
 		this.indexSyncManager.construct();
 		this.perInstanceParamSyncManager.construct();
-		this.dispatchIndirectCommandSyncManager.construct();
+		this.drawIndirectCommandSyncManager.construct();
 		
 		glCheck!glEnableVertexAttribArray(0);
 		glCheck!glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)0 );
@@ -250,53 +249,20 @@ struct Renderer {
 	}
 	
 	void destruct() {
-		this.dispatchIndirectCommandSyncManager.destruct();
+		this.drawIndirectCommandSyncManager.destruct();
 		this.perInstanceParamSyncManager.destruct();
 		this.indexSyncManager.destruct();
 		this.vertexSyncManager.destruct();
-		this.dispatchIndirectCommandBuffer.destruct();
+		this.drawIndirectCommandBuffer.destruct();
 		this.perInstanceParamBuffer.destruct();
 		this.indexBuffer.destruct();
 		this.vertexBuffer.destruct();
 		this.shaderPipeline.destruct();
 		this.gbuffer.destruct();
 	}
-	
-	//	void uploadModelData(GlArrayBuffer!VertexData vertexBuffer, GlElementArrayBuffer!IndexData indexBuffer, ModelData modelData) {
-	//		//TODO: wait for buffer range
-	//		//mBufferLockManager.WaitForLockedRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
-	//
-	//		// TODO: check if buffers are bound. they should always be bound here!
-	//
-	//		// we need to store all models in one giant vbo to use glMultiDrawElementsIndirect. 
-	//		// TODO: implement triple buffering. -> use vertexBuffer and indexBuffer as giant ring buffers
-	//		GLuint vertexBufferOffset = 0;
-	//		GLuint indexBufferOffset = 0;
-	//		
-	//		foreach(meshData; modelData.meshData) {
-	//			import std.c.string: memcpy;
-	//			//upload vertex data
-	//			assert(this.vertexBuffer.length >= meshData.vertexData.length);
-	//			memcpy(this.vertexBuffer.data + vertexBufferOffset, meshData.vertexData.ptr, meshData.vertexData.length * VertexData.sizeof);
-	//			vertexBufferOffset += meshData.vertexData.length * VertexData.sizeof;
-	//			//upload index data
-	//			assert(this.indexBuffer.length >= meshData.indexData.length);
-	//			memcpy(this.indexBuffer.data + indexBufferOffset, meshData.indexData.ptr, meshData.indexData.length * IndexData.sizeof);
-	//			indexBufferOffset += meshData.indexData.length * IndexData.sizeof;
-	//		}
-	//	}
 
 	void renderOneFrame(ref Scene scene, ref Camera camera, ref GlRenderTarget renderTarget, ref Viewport viewport)  {
-		// bind buffers
-		this.vertexBuffer.bind();
-		this.indexBuffer.bind();
-		this.perInstanceParamBuffer.bind();
-		this.dispatchIndirectCommandBuffer.bind();
-
-		// clear scene
-		glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-		glCheck!glClearDepth(1.0f);
-		glCheck!glClearColor(0, 0.3, 0, 1);
+		"-----------begin renderOneFrame---------".log;
 
 		// calc if we have to wrap our buffer
 		if(vertexRingbufferIndex + scene.modelData.vertexCount >= this.vertexBuffer.length) {
@@ -307,70 +273,103 @@ struct Renderer {
 			indexRingbufferIndex = 0;
 		}
 		
-		if(dispatchIndirectCommandRingbufferIndex + scene.modelData.meshCount >= this.dispatchIndirectCommandBuffer.length) {
-			dispatchIndirectCommandRingbufferIndex = 0;
+		if(drawIndirectCommandRingbufferIndex + scene.modelData.meshCount >= this.drawIndirectCommandBuffer.length) {
+			drawIndirectCommandRingbufferIndex = 0;
 		}
 
 		// wait until GPU has finished rendereing from our desired buffer destination
+		log("vertexSyncManager.waitForLockedRange ", vertexRingbufferIndex, ", ", scene.modelData.vertexCount); 
 		this.vertexSyncManager.waitForLockedRange(vertexRingbufferIndex, scene.modelData.vertexCount);
+		log("indexSyncManager.waitForLockedRange ", indexRingbufferIndex, ", ", scene.modelData.indexCount); 
 		this.indexSyncManager.waitForLockedRange(indexRingbufferIndex, scene.modelData.indexCount);
-		this.dispatchIndirectCommandSyncManager.waitForLockedRange(dispatchIndirectCommandRingbufferIndex, scene.modelData.meshCount);
+		log("drawIndirectCommandSyncManager.waitForLockedRange ", drawIndirectCommandRingbufferIndex, ", ", scene.modelData.meshCount); 
+		this.drawIndirectCommandSyncManager.waitForLockedRange(drawIndirectCommandRingbufferIndex, scene.modelData.meshCount);
 
-		// backup the index, we'll need it for our draw command
-		auto dispatchIndirectCommandRingbufferIndexForThisFrame = dispatchIndirectCommandRingbufferIndex;
+		// bind buffers
+		this.vertexBuffer.bind();
+		this.indexBuffer.bind();
+		this.perInstanceParamBuffer.bind();
+		this.drawIndirectCommandBuffer.bind();
+
+		//bind gbuffer
+		glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gbuffer.fbo); scope(exit) glCheck!glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 
+		GLenum[] drawBuffers = [GL_COLOR_ATTACHMENT0 + 0, GL_COLOR_ATTACHMENT0 + 1, GL_COLOR_ATTACHMENT0 + 2];
+		glCheck!glDrawBuffers(drawBuffers.length, drawBuffers.ptr); scope(exit) glCheck!glDrawBuffer(GL_NONE);
+		
+		// enable depth mask _before_ glClear ing the depth buffer!
+		glCheck!glDepthMask(GL_TRUE); scope(exit) glCheck!glDepthMask(GL_FALSE);
+		glCheck!glEnable(GL_DEPTH_TEST); scope(exit) glCheck!glDisable(GL_DEPTH_TEST);
+		glCheck!glDepthFunc(GL_LEQUAL);
+		
+		// clear scene
+		glCheck!glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+		glCheck!glClearDepth(1.0f);
+		glCheck!glClearColor(0, 0.3, 0, 1);
+		
+		glCheck!glViewport(0, 0, this.gbuffer.width, this.gbuffer.height);
+
+		// backup the indices, we'll need it for our draw command and locking
+		auto vertexRingbufferIndexForThisFrame = vertexRingbufferIndex;
+		auto indexRingbufferIndexForThisFrame = indexRingbufferIndex;
+		auto drawIndirectCommandRingbufferIndexForThisFrame = drawIndirectCommandRingbufferIndex;
 
 		// upload data to our buffers
 		foreach(meshData; scene.modelData.meshData) {
 			// upload vertex data
 			this.vertexBuffer.data[vertexRingbufferIndex .. vertexRingbufferIndex + meshData.vertexData.length] = meshData.vertexData[0 .. meshData.vertexData.length];
+
 			// upload index data
 			this.indexBuffer.data[indexRingbufferIndex .. indexRingbufferIndex + meshData.indexData.length] = meshData.indexData[0 .. meshData.indexData.length];
+
 			// draw command data
-			this.dispatchIndirectCommandBuffer.data[dispatchIndirectCommandRingbufferIndex] = GlDrawElementsIndirectCommand(
+			this.drawIndirectCommandBuffer.data[drawIndirectCommandRingbufferIndex] = GlDrawElementsIndirectCommand(
 				meshData.vertexData.length, 
 				1,
 				indexRingbufferIndex,
 				vertexRingbufferIndex,
 				0
 				);
+
 			// advance ringbuffers
 			vertexRingbufferIndex += meshData.vertexData.length;
 			indexRingbufferIndex += meshData.indexData.length;
-			++dispatchIndirectCommandRingbufferIndex;
+			++drawIndirectCommandRingbufferIndex;
 		}
-				
-		glCheck!glViewport(0, 0, this.gbuffer.width, this.gbuffer.height);
-		
-		// enable depth mask _before_ glClear ing the depth buffer!
-		glCheck!glDepthMask(GL_TRUE); scope(exit) glCheck!glDepthMask(GL_FALSE);
-		glCheck!glEnable(GL_DEPTH_TEST); scope(exit) glCheck!glDisable(GL_DEPTH_TEST);
-		glCheck!glDepthFunc(GL_LEQUAL);
 			
-		//glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), this.dispatchIndirectCommandBuffer.data + dispatchIndirectCommandRingbufferIndex, scene.modelData.meshCount, GlDrawElementsIndirectCommand.sizeof);
-		glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), cast(const void*)dispatchIndirectCommandRingbufferIndexForThisFrame, scene.modelData.meshCount, 0);
-
-		this.vertexSyncManager.lockRange(vertexRingbufferIndex, scene.modelData.vertexCount);
-		this.indexSyncManager.lockRange(indexRingbufferIndex, scene.modelData.indexCount);
-		this.dispatchIndirectCommandSyncManager.lockRange(dispatchIndirectCommandRingbufferIndex, scene.modelData.meshCount);
+		//bind pipeline
+		glCheck!glBindProgramPipeline(shaderPipeline.pipeline); scope(exit) glCheck!glBindProgramPipeline(0);
+
+		//draw
+		log("glMultiDrawElementsIndirect ", drawIndirectCommandRingbufferIndexForThisFrame, ", ", scene.modelData.meshCount, ", ", 0); 
+		glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), cast(const void*)drawIndirectCommandRingbufferIndexForThisFrame, scene.modelData.meshCount, 0);
+
+		// lock ranges
+		log("vertexSyncManager.lockRange ", vertexRingbufferIndexForThisFrame, ", ", scene.modelData.vertexCount); 
+		this.vertexSyncManager.lockRange(vertexRingbufferIndexForThisFrame, scene.modelData.vertexCount);
+		log("indexSyncManager.lockRange ", indexRingbufferIndexForThisFrame, ", ", scene.modelData.indexCount); 
+		this.indexSyncManager.lockRange(indexRingbufferIndexForThisFrame, scene.modelData.indexCount);
+		log("drawIndirectCommandSyncManager.lockRange ", drawIndirectCommandRingbufferIndexForThisFrame, ", ", scene.modelData.meshCount); 
+		this.drawIndirectCommandSyncManager.lockRange(drawIndirectCommandRingbufferIndexForThisFrame, scene.modelData.meshCount);
+		"-----------end renderOneFrame---------\n".log;
 	}
 	
 	debug {
 		void blitGBufferToScreen() {
-			glCheck!glBindFramebuffer(GL_READ_FRAMEBUFFER, this.gbuffer.fbo); scope(exit) glCheck!glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); 
-			
-			GLsizei width = this.gbuffer.width;
-			GLsizei height = this.gbuffer.height;
-			
-			scope(exit) glCheck!glReadBuffer(GL_NONE);
-			
-			glCheck!glReadBuffer(GL_COLOR_ATTACHMENT0 + 0);
-			glCheck!glBlitFramebuffer(0, 0, width, height, 0, height-300, 400, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-			
-			glCheck!glReadBuffer(GL_COLOR_ATTACHMENT0 + 1);
-			glCheck!glBlitFramebuffer(0, 0, width, height, 0, 0, 400, 300, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-			
-			glCheck!glReadBuffer(GL_COLOR_ATTACHMENT0 + 2);
-			glCheck!glBlitFramebuffer(0, 0, width, height, width-400, height-300, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+//			glCheck!glBindFramebuffer(GL_READ_FRAMEBUFFER, this.gbuffer.fbo); scope(exit) glCheck!glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); 
+//			
+//			GLsizei width = this.gbuffer.width;
+//			GLsizei height = this.gbuffer.height;
+//			
+//			scope(exit) glCheck!glReadBuffer(GL_NONE);
+//			
+//			glCheck!glReadBuffer(GL_COLOR_ATTACHMENT0 + 0);
+//			glCheck!glBlitFramebuffer(0, 0, width, height, 0, height-300, 400, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+//			
+//			glCheck!glReadBuffer(GL_COLOR_ATTACHMENT0 + 1);
+//			glCheck!glBlitFramebuffer(0, 0, width, height, 0, 0, 400, 300, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+//			
+//			glCheck!glReadBuffer(GL_COLOR_ATTACHMENT0 + 2);
+//			glCheck!glBlitFramebuffer(0, 0, width, height, width-400, height-300, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
 		}
 	}
 }

+ 32 - 26
source/gl/sync.d

@@ -3,6 +3,7 @@
 public import derelict.opengl3.gl3;
 import three.gl.util;
 
+enum kOneSecondInNanoSeconds = GLuint64(1000000000);
 
 struct GlSyncManager {
 private:
@@ -11,7 +12,7 @@ private:
 		size_t startOffset;
 		size_t length;
 		
-		bool overlaps(LockRange rhs) const {
+		bool overlaps(LockRange rhs) pure const const @safe nothrow {
 			return startOffset < (rhs.startOffset + rhs.length) && rhs.startOffset < (startOffset + length);
 		}
 	}
@@ -31,35 +32,13 @@ public:
 	void destruct() pure @safe nothrow @nogc {
 	}
 	
-	void waitForLockedRange(size_t lockBeginOffset, size_t lockLength) { 
+	void waitForLockedRange(size_t lockBeginOffset, size_t lockLength) nothrow { 
 		LockRange testRange = LockRange(lockBeginOffset, lockLength);
 		Lock[] swapLocks;
 		
 		foreach(ref lock; locks) {
 			if (testRange.overlaps(lock.range)) {
-				version(LockBusyWait) {
-					GLbitfield waitFlags = 0;
-					GLuint64 waitDuration = 0;
-					while(true) {
-						GLenum waitRet = glCheck!glClientWaitSync(lock.sync, waitFlags, waitDuration);
-						if (waitRet == GL_ALREADY_SIGNALED || waitRet == GL_CONDITION_SATISFIED) {
-							return;
-						}
-						
-						if (waitRet == GL_WAIT_FAILED) {
-							assert(!"Not sure what to do here. Probably raise an exception or something.");
-							return;
-						}
-						
-						// After the first time, need to start flushing, and wait for a looong time.
-						waitFlags = GL_SYNC_FLUSH_COMMANDS_BIT;
-						waitDuration = kOneSecondInNanoSeconds;
-					}
-				} 
-				else {
-					glCheck!glWaitSync(lock.sync, 0, GL_TIMEOUT_IGNORED);
-				}
-				
+				waitForSync(lock.sync);
 				glCheck!glDeleteSync(lock.sync);
 			} 
 			else {
@@ -71,9 +50,36 @@ public:
 		swap(locks, swapLocks);
 	}
 	
-	void lockRange(size_t lockBeginOffset, size_t lockLength) {
+	void lockRange(size_t lockBeginOffset, size_t lockLength) nothrow {
 		LockRange newRange = LockRange(lockBeginOffset, lockLength);
+		//TODO: glCheck!
 		GLsync syncName = glCheck!glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 		locks ~= Lock(newRange, syncName);
 	}
+
+private:
+	void waitForSync(ref GLsync sync) nothrow {
+		version(LockBusyWait) {
+			GLbitfield waitFlags = 0;
+			GLuint64 waitDuration = 0;
+			while(true) {
+				GLenum waitRet = glCheck!glClientWaitSync(sync, waitFlags, waitDuration);
+				if (waitRet == GL_ALREADY_SIGNALED || waitRet == GL_CONDITION_SATISFIED) {
+					return;
+				}
+				
+				if (waitRet == GL_WAIT_FAILED) {
+					assert(!"Not sure what to do here. Probably raise an exception or something.");
+					return;
+				}
+				
+				// After the first time, need to start flushing, and wait for a looong time.
+				waitFlags = GL_SYNC_FLUSH_COMMANDS_BIT;
+				waitDuration = kOneSecondInNanoSeconds;
+			}
+		} 
+		else {
+			glCheck!glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+		}
+	}
 }