Explorar o código

fixed draw command bug, and renamed some vars

Zoadian %!s(int64=11) %!d(string=hai) anos
pai
achega
594006276b
Modificáronse 4 ficheiros con 54 adicións e 44 borrados
  1. 5 1
      source/app.d
  2. 1 1
      source/gl/draw.d
  3. 43 40
      source/gl/renderer.d
  4. 5 2
      source/three/mesh.d

+ 5 - 1
source/app.d

@@ -73,7 +73,11 @@ void main() {
 	// Create Scene
 	//------------------------------------------------
 	scene.modelData = loadModelData("C:/Coding/models/Collada/duck.dae");
-	
+	log("Model: ", scene.modelData.filePath);
+	log("vertexCount: ", scene.modelData.vertexCount);
+	log("indexCount: ", scene.modelData.indexCount);
+	log("meshCount: ", scene.modelData.meshCount);
+
 	//------------------------------------------------
 	// Generate TweakBar
 	//------------------------------------------------

+ 1 - 1
source/gl/draw.d

@@ -3,7 +3,7 @@
 public import derelict.opengl3.gl3;
 import three.mesh;
 
-struct GlDrawElementsIndirectCommand {
+struct GlDrawCommand {
 	GLuint vertexCount;
 	GLuint instanceCount;
 	GLuint firstIndex;

+ 43 - 40
source/gl/renderer.d

@@ -16,10 +16,10 @@ import three.gl.sync;
 import three.gl.util;
 public import three.gl.renderTarget;
 
-enum maxVertices = 16 * 1024;
-enum maxIndices = 16 * 1024;
+enum maxVertices = 3*8500;
+enum maxIndices = 3*12636;
 enum maxPerInstanceParams = 1024;
-enum maxIndirectCommands = 1024;
+enum maxIndirectCommands = 3*1;
 
 
 
@@ -197,11 +197,6 @@ enum fragmentShaderSource = "
 ";
 
 
-struct RingbufferManager {
-	size_t offset;
-
-};
-
 
 //======================================================================================================================
 // 
@@ -212,7 +207,7 @@ 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 drawIndirectCommandBuffer; // is filled with DrawElementsIndirectCommand for each mesh each frame. shall be accessed as a ringbuffer
+	GlDrawIndirectBuffer!GlDrawCommand drawCommandBuffer; // is filled with DrawElementsIndirectCommand for each mesh each frame. shall be accessed as a ringbuffer
 	GlSyncManager vertexSyncManager;
 	GlSyncManager indexSyncManager;
 	GlSyncManager perInstanceParamSyncManager;
@@ -220,7 +215,7 @@ struct Renderer {
 	size_t vertexRingbufferIndex = 0;
 	size_t indexRingbufferIndex = 0;
 	size_t perInstanceParamRingbufferIndex = 0;
-	size_t drawIndirectCommandRingbufferIndex = 0;
+	size_t drawCommandRingbufferIndex = 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;
@@ -231,12 +226,12 @@ struct Renderer {
 		this.vertexBuffer.construct(maxVertices, createFlags, mapFlags);
 		this.indexBuffer.construct(maxIndices, createFlags, mapFlags);
 		this.perInstanceParamBuffer.construct(maxPerInstanceParams, createFlags, mapFlags);
-		this.drawIndirectCommandBuffer.construct(maxIndirectCommands, createFlags, mapFlags);
+		this.drawCommandBuffer.construct(maxIndirectCommands, createFlags, mapFlags);
 		this.vertexSyncManager.construct();
 		this.indexSyncManager.construct();
 		this.perInstanceParamSyncManager.construct();
 		this.drawIndirectCommandSyncManager.construct();
-		
+
 		glCheck!glEnableVertexAttribArray(0);
 		glCheck!glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)0 );
 		glCheck!glEnableVertexAttribArray(1);
@@ -252,7 +247,7 @@ struct Renderer {
 		this.perInstanceParamSyncManager.destruct();
 		this.indexSyncManager.destruct();
 		this.vertexSyncManager.destruct();
-		this.drawIndirectCommandBuffer.destruct();
+		this.drawCommandBuffer.destruct();
 		this.perInstanceParamBuffer.destruct();
 		this.indexBuffer.destruct();
 		this.vertexBuffer.destruct();
@@ -261,41 +256,49 @@ struct Renderer {
 	}
 
 	void renderOneFrame(ref Scene scene, ref Camera camera, ref GlRenderTarget renderTarget, ref Viewport viewport)  {
+		assert(vertexBuffer.length >= 3 * scene.modelData.vertexCount);
+		assert(indexBuffer.length >= 3 * scene.modelData.indexCount);
+		assert(drawCommandBuffer.length >= 3 * scene.modelData.meshCount);
+
 		// calc if we have to wrap our buffer
-		if(vertexRingbufferIndex + scene.modelData.vertexCount >= this.vertexBuffer.length) {
+		if(vertexRingbufferIndex + scene.modelData.vertexCount > this.vertexBuffer.length) {
 			vertexRingbufferIndex = 0;
 		}
 		
-		if(indexRingbufferIndex + scene.modelData.indexCount >= this.indexBuffer.length) {
+		if(indexRingbufferIndex + scene.modelData.indexCount > this.indexBuffer.length) {
 			indexRingbufferIndex = 0;
 		}
 		
-		if(drawIndirectCommandRingbufferIndex + scene.modelData.meshCount >= this.drawIndirectCommandBuffer.length) {
-			drawIndirectCommandRingbufferIndex = 0;
+		if(drawCommandRingbufferIndex + scene.modelData.meshCount > this.drawCommandBuffer.length) {
+			drawCommandRingbufferIndex = 0;
 		}
 
 		// wait until GPU has finished rendereing from our desired buffer destination
 		this.vertexSyncManager.waitForLockedRange(vertexRingbufferIndex, scene.modelData.vertexCount);
+//		log("vertexSyncManager: ", vertexRingbufferIndex, " ", scene.modelData.vertexCount);
 		this.indexSyncManager.waitForLockedRange(indexRingbufferIndex, scene.modelData.indexCount);
-		this.drawIndirectCommandSyncManager.waitForLockedRange(drawIndirectCommandRingbufferIndex, scene.modelData.meshCount);
+//		log("indexSyncManager: ", indexRingbufferIndex, " ", scene.modelData.indexCount);
+		this.drawIndirectCommandSyncManager.waitForLockedRange(drawCommandRingbufferIndex, scene.modelData.meshCount);
+//		log("drawIndirectCommandSyncManager: ", drawCommandRingbufferIndex, " ", scene.modelData.meshCount);
 
 		// bind buffers
 		this.vertexBuffer.bind(); scope(exit) this.vertexBuffer.unbind();
 		this.indexBuffer.bind(); scope(exit) this.indexBuffer.unbind();
 		this.perInstanceParamBuffer.bind(); scope(exit) this.perInstanceParamBuffer.unbind();
-		this.drawIndirectCommandBuffer.bind(); scope(exit) this.drawIndirectCommandBuffer.unbind();
+		this.drawCommandBuffer.bind(); scope(exit) this.drawCommandBuffer.unbind();
 
 		//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!glEnable(GL_DEPTH_TEST);
+		glCheck!glDepthFunc(GL_LEQUAL);
+		glCheck!glDisable(GL_SCISSOR_TEST);
+		glCheck!glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+		glCheck!glDepthMask(GL_TRUE); // enable depth mask _before_ glClear ing the depth buffer!
+		glCheck!glStencilMask(0xFFFFFFFF);
 		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);
@@ -303,11 +306,13 @@ struct Renderer {
 		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;
+		auto curVertexRingbufferIndex = vertexRingbufferIndex;
+		auto curIndexRingbufferIndex = indexRingbufferIndex;
+		auto curDrawCommandRingbufferIndex = drawCommandRingbufferIndex;
 
 		// upload data to our buffers
+//		foreach(model; scene.modelData) {
+		//			foreach(meshData; model.meshData) {
 		foreach(meshData; scene.modelData.meshData) {
 			// upload vertex data
 			this.vertexBuffer.data[vertexRingbufferIndex .. vertexRingbufferIndex + meshData.vertexData.length] = meshData.vertexData[0 .. meshData.vertexData.length];
@@ -316,30 +321,28 @@ struct Renderer {
 			this.indexBuffer.data[indexRingbufferIndex .. indexRingbufferIndex + meshData.indexData.length] = meshData.indexData[0 .. meshData.indexData.length];
 
 			// draw command data
-			this.drawIndirectCommandBuffer.data[drawIndirectCommandRingbufferIndex] = GlDrawElementsIndirectCommand(
-				meshData.vertexData.length, 
-				1,
-				indexRingbufferIndex,
-				vertexRingbufferIndex,
-				0
-				);
+			this.drawCommandBuffer.data[drawCommandRingbufferIndex] = GlDrawCommand(meshData.indexData.length, 1, indexRingbufferIndex, vertexRingbufferIndex, 0);
+
+			log(this.drawCommandBuffer.data[drawCommandRingbufferIndex]);
 
 			// advance ringbuffers
 			vertexRingbufferIndex += meshData.vertexData.length;
 			indexRingbufferIndex += meshData.indexData.length;
-			++drawIndirectCommandRingbufferIndex;
+			++drawCommandRingbufferIndex;
 		}
+//			}
+//		}
 			
 		// bind pipeline
 		glCheck!glBindProgramPipeline(shaderPipeline.pipeline); scope(exit) glCheck!glBindProgramPipeline(0);
 
 		// draw
-		glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), cast(const void*)(drawIndirectCommandRingbufferIndexForThisFrame * GlDrawElementsIndirectCommand.sizeof), scene.modelData.meshCount, 0);
+		glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), cast(const void*)(curDrawCommandRingbufferIndex * GlDrawCommand.sizeof), scene.modelData.meshCount, 0);
 
 		// lock ranges
-		this.vertexSyncManager.lockRange(vertexRingbufferIndexForThisFrame, scene.modelData.vertexCount);
-		this.indexSyncManager.lockRange(indexRingbufferIndexForThisFrame, scene.modelData.indexCount);
-		this.drawIndirectCommandSyncManager.lockRange(drawIndirectCommandRingbufferIndexForThisFrame, scene.modelData.meshCount);
+		this.vertexSyncManager.lockRange(curVertexRingbufferIndex, scene.modelData.vertexCount);
+		this.indexSyncManager.lockRange(curIndexRingbufferIndex, scene.modelData.indexCount);
+		this.drawIndirectCommandSyncManager.lockRange(curDrawCommandRingbufferIndex, scene.modelData.meshCount);
 	}
 	
 	debug {

+ 5 - 2
source/three/mesh.d

@@ -14,16 +14,18 @@ struct MeshData {
 }
 
 struct ModelData {
+	string filePath;
 	MeshData[] meshData;
 
 	size_t vertexCount() const @safe {
 		import std.algorithm : map, reduce;
-		return meshData.map!("a.vertexData.length").reduce!("a + b");
+
+		return meshData.length == 0 ? 0 : meshData.map!("a.vertexData.length").reduce!("a + b");
 	}
 	
 	size_t indexCount() const @safe {
 		import std.algorithm : map, reduce;
-		return meshData.map!("a.indexData.length").reduce!("a + b");
+		return meshData.length == 0 ? 0 : meshData.map!("a.indexData.length").reduce!("a + b");
 	}
 
 	size_t meshCount() const @safe {
@@ -37,6 +39,7 @@ ModelData loadModelData(string filePath) {
 	auto scene = aiImportFile(filePath.toStringz(),	aiProcess_Triangulate); scope(exit) aiReleaseImport(scene);
 
 	ModelData modelData;
+	modelData.filePath = filePath;
 	modelData.meshData.length = scene.mNumMeshes;
 
 	for(uint m = 0; m < scene.mNumMeshes; ++m) {