Jelajahi Sumber

code cleaned up

Zoadian 11 tahun lalu
induk
melakukan
f7bd4d3879

+ 7 - 9
source/app.d

@@ -43,7 +43,7 @@ void main() {
 	DerelictAntTweakBar.load();
 	if(!glfwInit()) throw new Exception("Initialising GLFW failed"); scope(exit) glfwTerminate();
 
-	construct(window, "Three.d", 1600, 900); scope(exit) destruct(window);
+	window.construct("Three.d", 1600, 900); scope(exit) window.destruct();
 	
 	try {
 		GLVersion glVersion = DerelictGL3.reload();
@@ -58,18 +58,16 @@ void main() {
 	if(TwInit(TW_OPENGL_CORE, null) == 0) throw new Exception("Initialising AntTweakBar failed"); scope(exit) TwTerminate();
 
 
-	construct(viewport); scope(exit) destruct(viewport);
-	construct(scene); scope(exit) destruct(scene);
-	construct(camera); scope(exit) destruct(camera);
-	construct(renderTarget, window.width, window.height); scope(exit) destruct(renderTarget);
-	construct(renderer, window.width, window.height); scope(exit) destruct(renderer);
+	viewport.construct(); scope(exit) viewport.destruct();
+	scene.construct(); scope(exit) scene.destruct();
+	camera.construct(); scope(exit) camera.destruct();
+	renderTarget.construct(window.width, window.height); scope(exit) renderTarget.destruct();
+	renderer.construct(window.width, window.height); scope(exit) renderer.destruct();
 
 	//------------------------------------------------
 	// Create Scene
 	//------------------------------------------------
-	ModelData modelData;
-	loadModelData(modelData, "C:/Coding/models/Collada/duck.dae");
-	renderer.uploadModelData(modelData);
+	ModelData modelData = loadModelData("C:/Coding/models/Collada/duck.dae");
 	
 	//------------------------------------------------
 	// Generate TweakBar

+ 60 - 0
source/gl/buffer.d

@@ -0,0 +1,60 @@
+module three.gl.buffer;
+
+import three.common;
+
+enum GlBufferTarget {
+	Array = GL_ARRAY_BUFFER, 
+	AtomicCounter = GL_ATOMIC_COUNTER_BUFFER, 
+	CopyRead= GL_COPY_READ_BUFFER, 
+	CopyWrite = GL_COPY_WRITE_BUFFER, 
+	DrawIndirect = GL_DRAW_INDIRECT_BUFFER, 
+	DispatchIndirect = GL_DISPATCH_INDIRECT_BUFFER,
+	ElementArray = GL_ELEMENT_ARRAY_BUFFER, 
+	PixelPack = GL_PIXEL_PACK_BUFFER, 
+	PixelUnpack = GL_PIXEL_UNPACK_BUFFER, 
+	QueryBuffer = GL_QUERY_BUFFER,
+	ShaderStorage = GL_SHADER_STORAGE_BUFFER,
+	Texture = GL_TEXTURE_BUFFER, 
+	TransformFeedback = GL_TRANSFORM_FEEDBACK_BUFFER,
+	Uniform = GL_UNIFORM_BUFFER
+}
+
+struct GlBuffer(GlBufferTarget Target, T) {
+	alias BufferTarget = Target;
+	alias ValueType = T;
+	GLuint handle;
+	GLuint length;
+	T* data;
+	
+	void construct(GLuint length, GLbitfield createFlags, GLbitfield mapFlags) {
+		glCheck!glGenBuffers(1, &this.handle);
+		bind();
+		glCheck!glBufferStorage(Target, length * T.sizeof, null, createFlags);
+		this.data = cast(T*)glCheck!glMapBufferRange(Target, 0, length * T.sizeof, mapFlags);
+		this.length = length;
+		if (this.data is null) {
+			throw new Exception("glMapBufferRange failed, probable bug.");
+		}
+	}
+	
+	void destruct() {
+		bind(); // bind!
+		glCheck!glUnmapBuffer(Target);
+		glCheck!glDeleteBuffers(1, &this.handle);
+	}
+	
+	void bind() {
+		glCheck!glBindBuffer(Target, this.handle);
+	}
+	
+//	void unbind() {
+//		glCheck!glBindBuffer(Target, 0);
+//	}
+}
+
+alias GlArrayBuffer(T) = GlBuffer!(GlBufferTarget.Array, T);
+alias GlElementArrayBuffer(T) = GlBuffer!(GlBufferTarget.ElementArray, T);
+alias GlShaderStorageBuffer(T) = GlBuffer!(GlBufferTarget.ShaderStorage, T);
+alias GlDispatchIndirectBuffer(T) = GlBuffer!(GlBufferTarget.DispatchIndirect, T);
+alias GlTextureBuffer(T) = GlBuffer!(GlBufferTarget.Texture, T);
+alias GlUniformBuffer(T) = GlBuffer!(GlBufferTarget.Uniform, T);

+ 16 - 0
source/gl/draw.d

@@ -0,0 +1,16 @@
+module three.gl.draw;
+
+import three.common;
+import three.mesh;
+
+struct GlDrawElementsIndirectCommand {
+	GLuint count;
+	GLuint instanceCount;
+	GLuint firstIndex;
+	GLuint baseVertex;
+	GLuint baseInstance;
+}
+
+struct GlDrawParameter {
+	Matrix4 transformationMatrix;
+}

+ 70 - 0
source/gl/sync.d

@@ -0,0 +1,70 @@
+module three.gl.sync;
+
+import three.common;
+
+
+struct GlSyncManager {
+	struct LockRange
+	{
+		size_t startOffset;
+		size_t length;
+		
+		bool overlaps(LockRange rhs) const {
+			return startOffset < (rhs.startOffset + rhs.length) && rhs.startOffset < (startOffset + length);
+		}
+	}
+	
+	struct Lock
+	{
+		LockRange range;
+		GLsync sync;
+	}
+	
+	Lock[] locks;
+	
+	void waitForLockedRange(size_t lockBeginOffset, size_t lockLength) { 
+		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);
+				}
+				
+				glCheck!glDeleteSync(lock.sync);
+			} 
+			else {
+				swapLocks ~= lock;
+			}
+		}
+		
+		import std.algorithm : swap;
+		swap(locks, swapLocks);
+	}
+	
+	void lockRange(size_t lockBeginOffset, size_t lockLength) {
+		LockRange newRange = LockRange(lockBeginOffset, lockLength);
+		GLsync syncName = glCheck!glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+		locks ~= Lock(newRange, syncName);
+	}
+}

+ 5 - 7
source/three/camera.d

@@ -3,11 +3,9 @@
 import three.common;
 
 struct Camera {
+	void construct() pure @safe nothrow @nogc {
+	}
+	
+	void destruct() pure @safe nothrow @nogc {
+	}
 }
-
-void construct(out Camera camera) pure @safe nothrow @nogc {
-}
-
-void destruct(ref Camera camera) pure @safe nothrow @nogc {
-	camera = Camera.init;
-}

+ 3 - 2
source/three/mesh.d

@@ -42,11 +42,12 @@ struct ModelData {
 	MeshData[] meshData;
 }
 
-void loadModelData(out ModelData modelData, string filePath) {
+ModelData loadModelData(string filePath) {
 	import std.traits;
 	import std.string : toStringz;
 	auto scene = aiImportFile(filePath.toStringz(),	aiProcess_Triangulate); scope(exit) aiReleaseImport(scene);
 
+	ModelData modelData;
 	modelData.meshData.length = scene.mNumMeshes;
 
 	for(uint m = 0; m < scene.mNumMeshes; ++m) {	
@@ -89,6 +90,6 @@ void loadModelData(out ModelData modelData, string filePath) {
 				modelData.meshData[m].indexData[curIndexDataIdx++] = meshData.mFaces[f].mIndices[i];		
 			}
 		}
-
 	}
+	return modelData;
 }

+ 86 - 250
source/three/renderer.d

@@ -12,6 +12,9 @@ import std.exception : collectException;
 
 import std.experimental.logger;
 
+import three.gl.buffer;
+import three.gl.draw;
+import three.gl.sync;
 
 enum maxVertices = 1024;
 enum maxIndices = 1024;
@@ -22,246 +25,75 @@ enum kOneSecondInNanoSeconds = GLuint64(1000000000);
 
 
 
-//======================================================================================================================
-// 
-//======================================================================================================================
-enum GlBufferTarget {
-	Array = GL_ARRAY_BUFFER, 
-	AtomicCounter = GL_ATOMIC_COUNTER_BUFFER, 
-	CopyRead= GL_COPY_READ_BUFFER, 
-	CopyWrite = GL_COPY_WRITE_BUFFER, 
-	DrawIndirect = GL_DRAW_INDIRECT_BUFFER, 
-	DispatchIndirect = GL_DISPATCH_INDIRECT_BUFFER,
-	ElementArray = GL_ELEMENT_ARRAY_BUFFER, 
-	PixelPack = GL_PIXEL_PACK_BUFFER, 
-	PixelUnpack = GL_PIXEL_UNPACK_BUFFER, 
-	QueryBuffer = GL_QUERY_BUFFER,
-	ShaderStorage = GL_SHADER_STORAGE_BUFFER,
-	Texture = GL_TEXTURE_BUFFER, 
-	TransformFeedback = GL_TRANSFORM_FEEDBACK_BUFFER,
-	Uniform = GL_UNIFORM_BUFFER
-}
-
-struct GlBuffer(GlBufferTarget Target, T) {
-	alias BufferTarget = Target;
-	alias ValueType = T;
-	GLuint handle;
-	GLuint length;
-	T* data;
-}
-
-void construct(GlBufferTarget Target, T)(out GlBuffer!(Target, T) buffer, GLuint length, GLbitfield createFlags, GLbitfield mapFlags) {
-	glCheck!glGenBuffers(1, &buffer.handle);
-	glCheck!glBindBuffer(Target, buffer.handle);
-	glCheck!glBufferStorage(Target, length * T.sizeof, null, createFlags);
-	buffer.data = cast(T*)glCheck!glMapBufferRange(Target, 0, length * T.sizeof, mapFlags);
-	buffer.length = length;
-	if (buffer.data is null) {
-		throw new Exception("glMapBufferRange failed, probable bug.");
-	}
-}
-
-void destruct(GlBufferTarget Target, T)(ref GlBuffer!(Target, T) buffer) {
-	glCheck!glUnmapBuffer(Target);
-	glCheck!glBindBuffer(Target, 0);
-	glCheck!glDeleteBuffers(1, &buffer.handle);
-	buffer = buffer.init;
-}
-
-void bind(GlBufferTarget Target, T)(ref GlBuffer!(Target, T) buffer) {
-	glCheck!glBindBuffer(Target, buffer.handle);
-}
-
-void unbind(GlBufferTarget Target, T)(ref GlBuffer!(Target, T) buffer) {
-	glCheck!glBindBuffer(Target, 0);
-}
-
-alias GlArrayBuffer(T) = GlBuffer!(GlBufferTarget.Array, T);
-alias GlElementArrayBuffer(T) = GlBuffer!(GlBufferTarget.ElementArray, T);
-alias GlShaderStorageBuffer(T) = GlBuffer!(GlBufferTarget.ShaderStorage, T);
-alias GlDispatchIndirectBuffer(T) = GlBuffer!(GlBufferTarget.DispatchIndirect, T);
-alias GlTextureBuffer(T) = GlBuffer!(GlBufferTarget.Texture, T);
-alias GlUniformBuffer(T) = GlBuffer!(GlBufferTarget.Uniform, T);
-
-
-
-//======================================================================================================================
-// 
-//======================================================================================================================
-struct DrawElementsIndirectCommand {
-	GLuint count;
-	GLuint instanceCount;
-	GLuint firstIndex;
-	GLuint baseVertex;
-	GLuint baseInstance;
-}
-
-
-
-
-struct DrawParameter {
-	Matrix4 transformationMatrix;
-}
-
-
-
-
 //======================================================================================================================
 // 
 //======================================================================================================================
 struct Renderer {
 	uint width;
 	uint height;
-	GLsync sync;
+	GlSyncManager syncManager;
 	GlArrayBuffer!VertexData vertexBuffer; // vertex data for all meshes
 	GlElementArrayBuffer!IndexData indexBuffer; //index data for all meshes
-	GlShaderStorageBuffer!DrawParameter perInstanceParamBuffer; // is filled with draw parameters for each instance each frame. shall be accessed as a ringbuffer
-	GlDispatchIndirectBuffer!DrawElementsIndirectCommand dispatchIndirectCommandBuffer; // is filled with DrawElementsIndirectCommand for each mesh each frame. shall be accessed as a ringbuffer
-}
-
-void construct(out Renderer renderer, uint width, uint height) {
-	GLbitfield createFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;//TODO: ?? | GL_MAP_DYNAMIC_STORAGE_BIT;
-	GLbitfield mapFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
-	
-	renderer.vertexBuffer.construct(bufferCount * maxVertices, createFlags, mapFlags);
-	renderer.indexBuffer.construct(bufferCount * maxIndices, createFlags, mapFlags);
-	renderer.perInstanceParamBuffer.construct(bufferCount * maxPerInstanceParams, createFlags, mapFlags);
-	renderer.dispatchIndirectCommandBuffer.construct(bufferCount * maxIndirectCommands, createFlags, mapFlags);
-
-	glCheck!glEnableVertexAttribArray(0);
-	glCheck!glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)0 );
-	glCheck!glEnableVertexAttribArray(1);
-	glCheck!glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)3 );
-	glCheck!glEnableVertexAttribArray(2);
-	glCheck!glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)6 );
-	glCheck!glEnableVertexAttribArray(3);
-	glCheck!glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)10 );
-}
-
-void destruct(ref Renderer renderer) {
-	renderer.vertexBuffer.destruct();
-	renderer.indexBuffer.destruct();
-	renderer.perInstanceParamBuffer.destruct();
-	renderer.dispatchIndirectCommandBuffer.destruct();
-	renderer = renderer.init;
-}
-
-
-
-
-struct BufferLockManager(bool UseBusyCpu) {
-	struct BufferRange
-	{
-		size_t startOffset;
-		size_t length;
-
-		bool overlaps(BufferRange rhs) const {
-			return startOffset < (rhs.startOffset + rhs.length) && rhs.startOffset < (startOffset + length);
-		}
-	}
-	
-	struct BufferLock
-	{
-		BufferRange range;
-		GLsync syncObj;
+	GlShaderStorageBuffer!GlDrawParameter perInstanceParamBuffer; // is filled with draw parameters for each instance each frame. shall be accessed as a ringbuffer
+	GlDispatchIndirectBuffer!GlDrawElementsIndirectCommand dispatchIndirectCommandBuffer; // is filled with DrawElementsIndirectCommand for each mesh each frame. shall be accessed as a ringbuffer
+
+	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;
+		GLbitfield mapFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
+		
+		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);
+
+		glCheck!glEnableVertexAttribArray(0);
+		glCheck!glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)0 );
+		glCheck!glEnableVertexAttribArray(1);
+		glCheck!glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)3 );
+		glCheck!glEnableVertexAttribArray(2);
+		glCheck!glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)6 );
+		glCheck!glEnableVertexAttribArray(3);
+		glCheck!glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, VertexData.sizeof, cast(GLvoid*)10 );
 	}
 
-	BufferLock[] bufferLocks;
-}
-
-void waitForLockedRange(bool UseBusyCpu)(ref BufferLockManager!UseBusyCpu bufferLockManager, size_t lockBeginOffset, size_t lockLength) { 
-	BufferRange testRange = BufferRange(lockBeginOffset, lockLength);
-	BufferLock[] swapLocks;
-
-	foreach(ref bl; bufferLockManager.bufferLocks) {
-		if (testRange.overlaps(bl.range)) {
-			static if(UseBusyCpu) {
-				GLbitfield waitFlags = 0;
-				GLuint64 waitDuration = 0;
-				while(true) {
-					GLenum waitRet = glCheck!glClientWaitSync(syncObj, 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(syncObj, 0, GL_TIMEOUT_IGNORED);
-			}
+	void destruct() {
+		this.vertexBuffer.destruct();
+		this.indexBuffer.destruct();
+		this.perInstanceParamBuffer.destruct();
+		this.dispatchIndirectCommandBuffer.destruct();
+	}
 
-			glCheck!glDeleteSync(bl.syncObj);
-		} 
-		else {
-			swapLocks ~= bl;
+	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;
 		}
 	}
 
-	import std.algorithm : swap;
-	swap(bufferLockManager.bufferLocks, swapLocks);
-}
-
-void lockRange(bool UseBusyCpu)(ref BufferLockManager!UseBusyCpu bufferLockManager, size_t lockBeginOffset, size_t lockLength) {
-	BufferRange newRange = BufferRange(lockBeginOffset, lockLength);
-	GLsync syncName = glCheck!glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-	BufferLock newLock = BufferLock(newRange, syncName);	
-	bufferLockManager.bufferLocks ~= newLock;
-}
-
+	void renderOneFrame(ref Scene scene, ref Camera camera, ref RenderTarget renderTarget, ref Viewport viewport) {
 
-//void lockBuffer(ref Renderer renderer) {
-//	if(renderer.sync) {
-//		glDeleteSync(renderer.sync);	
-//	}
-//	renderer.sync = glCheck!glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-//}
-//
-//void waitBuffer(ref Renderer renderer) {
-//	if(renderer.sync) {
-//		while(true) {
-//			GLenum waitReturn = glClientWaitSync(renderer.sync, GL_SYNC_FLUSH_COMMANDS_BIT, 1);
-//			if (waitReturn == GL_ALREADY_SIGNALED || waitReturn == GL_CONDITION_SATISFIED) {
-//				return;
-//			}
-//		}
-//	}
-//}
+		// wait until GPU has finished rendereing from our desired buffer destination
+		//TODO: syncManager.WaitForLockedRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
 
-void uploadModelData(ref Renderer renderer, ModelData modelData) {
-	//TODO: wait for buffer range
-	//mBufferLockManager.WaitForLockedRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
-	
-	renderer.vertexBuffer.bind();
-	renderer.indexBuffer.bind();
-	// 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(renderer.vertexBuffer.length >= meshData.vertexData.length);
-		memcpy(renderer.vertexBuffer.data + vertexBufferOffset, meshData.vertexData.ptr, meshData.vertexData.length * VertexData.sizeof);
-		vertexBufferOffset += meshData.vertexData.length * VertexData.sizeof;
-		//upload index data
-		assert(renderer.indexBuffer.length >= meshData.indexData.length);
-		memcpy(renderer.indexBuffer.data + indexBufferOffset, meshData.indexData.ptr, meshData.indexData.length * IndexData.sizeof);
-		indexBufferOffset += meshData.indexData.length * IndexData.sizeof;
-	}
-}
-
-void renderOneFrame(ref Renderer renderer, ref Scene scene, ref Camera camera, ref RenderTarget renderTarget, ref Viewport viewport) {
-	
-	/*
+		/*
 		foreach(renderTarget) //framebuffer
 		foreach(pass)
 		foreach(material) //shaders
@@ -272,34 +104,38 @@ void renderOneFrame(ref Renderer renderer, ref Scene scene, ref Camera camera, r
 							glDrawElementsBaseVertex
 						}
 		*/	
-
-	GLsizei meshCount = 0;
-
-	glCheck!glViewport(0, 0, renderer.width, renderer.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);
-
-	// write draw parameters
-	
-	// write draw commmands
+		
+		GLsizei meshCount = 0;
+		
+		glCheck!glViewport(0, 0, this.width, this.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);
+		
+		// write draw parameters
+		
+		// write draw commmands
+		
+		// draw //TODO: pass offset (cast to ptr) into command buffer instead of null
+
+		
+		this.vertexBuffer.bind();
+		this.indexBuffer.bind();
+		this.perInstanceParamBuffer.bind();
+		this.dispatchIndirectCommandBuffer.bind();
+		
+		glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(this.indexBuffer.ValueType), null, meshCount, 0);
+
+		//TODO: syncManager.LockRange(mStartDestOffset, _vertices.size() * sizeof(Vec2));
+	}
 	
-	// draw //TODO: pass offset (cast to ptr) into command buffer instead of null
-
-
-	renderer.vertexBuffer.bind();
-	renderer.indexBuffer.bind();
-	renderer.perInstanceParamBuffer.bind();
-	renderer.dispatchIndirectCommandBuffer.bind();
+	debug {
+		void blitGBufferToScreen() {
+		}
+	}
+}
 
-	glCheck!glMultiDrawElementsIndirect(GL_TRIANGLES, toGlType!(renderer.indexBuffer.ValueType), null, meshCount, 0);
 
-	//TODO: lock buffer range
-}
 
-debug {
-	void blitGBufferToScreen(ref Renderer renderer) {
-	}
-}

+ 5 - 7
source/three/scene.d

@@ -4,11 +4,9 @@ import three.common;
 import three.mesh;
 
 struct Scene {
+	void construct() pure @safe nothrow @nogc {
+	}
+	
+	void destruct() pure @safe nothrow @nogc {
+	}
 }
-
-void construct(out Scene scene) pure @safe nothrow @nogc {
-}
-
-void destruct(ref Scene scene) pure @safe nothrow @nogc {
-	scene = Scene.init;
-}

+ 5 - 7
source/three/viewport.d

@@ -3,11 +3,9 @@
 import three.common;
 
 struct Viewport {
+	void construct() pure @safe nothrow @nogc {
+	}
+	
+	void destruct() pure @safe nothrow @nogc {
+	}
 }
-
-void construct(out Viewport viewport) pure @safe nothrow @nogc {
-}
-
-void destruct(ref Viewport viewport) pure @safe nothrow @nogc {
-	viewport = Viewport.init;
-}

+ 102 - 102
source/three/window.d

@@ -9,6 +9,108 @@ private:
 	KeyAction[int] _keyStates;
 	ButtonAction[int] _buttonStates;
 
+public:
+	void construct(string title, uint width, uint height) nothrow {
+		this._x = 0;
+		this._y = 0;
+		this._width = width;
+		this._height = height;
+		
+		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
+
+		glfwDefaultWindowHints();
+		glfwWindowHint(GLFW_RED_BITS, 8);
+		glfwWindowHint(GLFW_GREEN_BITS, 8);
+		glfwWindowHint(GLFW_BLUE_BITS, 8);
+		glfwWindowHint(GLFW_ALPHA_BITS, 0);
+		glfwWindowHint(GLFW_DEPTH_BITS, 24);
+		glfwWindowHint(GLFW_STENCIL_BITS, 8);
+		import std.string : toStringz;
+		this._glfwWindow = glfwCreateWindow(width, height, title.toStringz(), null, null);
+		assert(this._glfwWindow !is null);
+		
+		glfwSetWindowUserPointer(this._glfwWindow, cast(void*)&this);
+		glfwSetWindowPosCallback(this._glfwWindow, cast(GLFWwindowposfun)&_GLFWwindowposfun);
+		glfwSetWindowSizeCallback(this._glfwWindow, cast(GLFWwindowsizefun)&_GLFWwindowsizefun);
+		glfwSetWindowCloseCallback(this._glfwWindow, cast(GLFWwindowclosefun)&_GLFWwindowclosefun);
+		glfwSetWindowRefreshCallback(this._glfwWindow, cast(GLFWwindowrefreshfun)&_GLFWwindowrefreshfun);
+		glfwSetWindowIconifyCallback(this._glfwWindow, cast(GLFWwindowiconifyfun)&_GLFWwindowiconifyfun);
+		glfwSetMouseButtonCallback(this._glfwWindow, cast(GLFWmousebuttonfun)&_GLFWmousebuttonfun);
+		glfwSetCursorPosCallback(this._glfwWindow, cast(GLFWcursorposfun)&_GLFWcursorposfun);
+		//glfwSetCursorEnterCallback(this._glfwWindow, cast(GLFWcursorenterfunfun)&_GLFWcursorenterfunfun);
+		glfwSetScrollCallback(this._glfwWindow, cast(GLFWscrollfun)&_GLFWscrollfun);
+		glfwSetKeyCallback(this._glfwWindow, cast(GLFWkeyfun)&_GLFWkeyfun);
+		glfwSetCharCallback(this._glfwWindow, cast(GLFWcharfun)&_GLFWcharfun);
+		
+		glfwMakeContextCurrent(this._glfwWindow);
+	}
+	
+	void destruct() {
+		//	glfwSetWindowPosCallback(this._glfwWindow, null);
+		//	glfwSetWindowSizeCallback(this._glfwWindow, null);
+		//	glfwSetWindowCloseCallback(this._glfwWindow, null);
+		//	glfwSetWindowRefreshCallback(this._glfwWindow, null);
+		//	glfwSetWindowIconifyCallback(this._glfwWindow, null);
+		//	glfwSetMouseButtonCallback(this._glfwWindow, null);
+		//	glfwSetCursorPosCallback(this._glfwWindow, null);
+		//	//glfwSetCursorEnterCallback(this._glfwWindow, null);
+		//	glfwSetScrollCallback(this._glfwWindow, null);
+		//	glfwSetKeyCallback(this._glfwWindow, null);
+		//	glfwSetCharCallback(this._glfwWindow, null);
+		
+		glfwDestroyWindow(this._glfwWindow);
+	}
+	
+	void makeAktiveRenderWindow() nothrow @nogc {
+		glfwMakeContextCurrent(this._glfwWindow);
+	}
+	
+	void swapBuffers() nothrow @nogc {
+		glfwSwapBuffers(this._glfwWindow);
+	}
+	
+	void pollEvents() nothrow @nogc {
+		glfwPollEvents();
+	}
+	
+	@property void setTitle(string title) nothrow {
+		import std.string : toStringz;
+		glfwSetWindowTitle(this._glfwWindow, title.toStringz());
+	}
+	
+	KeyAction keyState(int key) pure @safe nothrow {
+		try {
+			return this._keyStates.get(key, KeyAction.Released);
+		}
+		catch(Exception) {
+			return KeyAction.Released;
+		}
+	}
+	
+	ButtonAction buttonState(int button) pure @safe nothrow {
+		try {
+			return this._buttonStates.get(button, ButtonAction.Released);
+		}
+		catch(Exception) {
+			return ButtonAction.Released;
+		}
+	}
+	
+	uint x() {
+		return this._x;
+	}
+	uint y() {
+		return this._y;
+	}
+	uint width() {
+		return this._width;
+	}
+	uint height() {
+		return this._height;
+	}
+
 public:							
 	void delegate(ref Window, int, int) onPosition;	 
 	void delegate(ref Window, int, int) onSize;	 
@@ -183,108 +285,6 @@ enum Key {
 	Menu = 348
 }
 
-void construct(out Window window, string title, uint width, uint height) nothrow {
-	window._x = 0;
-	window._y = 0;
-	window._width = width;
-	window._height = height;
-	
-	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
-
-	glfwDefaultWindowHints();
-	glfwWindowHint(GLFW_RED_BITS, 8);
-	glfwWindowHint(GLFW_GREEN_BITS, 8);
-	glfwWindowHint(GLFW_BLUE_BITS, 8);
-	glfwWindowHint(GLFW_ALPHA_BITS, 0);
-	glfwWindowHint(GLFW_DEPTH_BITS, 24);
-	glfwWindowHint(GLFW_STENCIL_BITS, 8);
-	import std.string : toStringz;
-	window._glfwWindow = glfwCreateWindow(width, height, title.toStringz(), null, null);
-	assert(window._glfwWindow !is null);
-	
-		glfwSetWindowUserPointer(window._glfwWindow, cast(void*)&window);
-		glfwSetWindowPosCallback(window._glfwWindow, cast(GLFWwindowposfun)&_GLFWwindowposfun);
-		glfwSetWindowSizeCallback(window._glfwWindow, cast(GLFWwindowsizefun)&_GLFWwindowsizefun);
-		glfwSetWindowCloseCallback(window._glfwWindow, cast(GLFWwindowclosefun)&_GLFWwindowclosefun);
-		glfwSetWindowRefreshCallback(window._glfwWindow, cast(GLFWwindowrefreshfun)&_GLFWwindowrefreshfun);
-		glfwSetWindowIconifyCallback(window._glfwWindow, cast(GLFWwindowiconifyfun)&_GLFWwindowiconifyfun);
-		glfwSetMouseButtonCallback(window._glfwWindow, cast(GLFWmousebuttonfun)&_GLFWmousebuttonfun);
-		glfwSetCursorPosCallback(window._glfwWindow, cast(GLFWcursorposfun)&_GLFWcursorposfun);
-		//glfwSetCursorEnterCallback(window._glfwWindow, cast(GLFWcursorenterfunfun)&_GLFWcursorenterfunfun);
-		glfwSetScrollCallback(window._glfwWindow, cast(GLFWscrollfun)&_GLFWscrollfun);
-		glfwSetKeyCallback(window._glfwWindow, cast(GLFWkeyfun)&_GLFWkeyfun);
-		glfwSetCharCallback(window._glfwWindow, cast(GLFWcharfun)&_GLFWcharfun);
-	
-	glfwMakeContextCurrent(window._glfwWindow);
-}
-
-void destruct(ref Window window) {
-//	glfwSetWindowPosCallback(window._glfwWindow, null);
-//	glfwSetWindowSizeCallback(window._glfwWindow, null);
-//	glfwSetWindowCloseCallback(window._glfwWindow, null);
-//	glfwSetWindowRefreshCallback(window._glfwWindow, null);
-//	glfwSetWindowIconifyCallback(window._glfwWindow, null);
-//	glfwSetMouseButtonCallback(window._glfwWindow, null);
-//	glfwSetCursorPosCallback(window._glfwWindow, null);
-//	//glfwSetCursorEnterCallback(this._glfwWindow, null);
-//	glfwSetScrollCallback(window._glfwWindow, null);
-//	glfwSetKeyCallback(window._glfwWindow, null);
-//	glfwSetCharCallback(window._glfwWindow, null);
-	
-	glfwDestroyWindow(window._glfwWindow);
-	
-	window = Window.init;
-}
-
-void makeAktiveRenderWindow(ref Window window) nothrow @nogc {
-	glfwMakeContextCurrent(window._glfwWindow);
-}
-
-void swapBuffers(ref Window window) nothrow @nogc {
-	glfwSwapBuffers(window._glfwWindow);
-}
-
-void pollEvents(ref Window window) nothrow @nogc {
-	glfwPollEvents();
-}
-
-@property void setTitle(ref Window window, string title) nothrow {
-	import std.string : toStringz;
-	glfwSetWindowTitle(window._glfwWindow, title.toStringz());
-}
-
-KeyAction keyState(ref Window window, int key) pure @safe nothrow {
-	try {
-		return window._keyStates.get(key, KeyAction.Released);
-	}
-	catch(Exception) {
-		return KeyAction.Released;
-	}
-}
-
-ButtonAction buttonState(ref Window window, int button) pure @safe nothrow {
-	try {
-		return window._buttonStates.get(button, ButtonAction.Released);
-	}
-	catch(Exception) {
-		return ButtonAction.Released;
-	}
-}
-
-uint x(ref Window window) {
-	return window._x;
-}
-uint y(ref Window window) {
-	return window._y;
-}
-uint width(ref Window window) {
-	return window._width;
-}
-uint height(ref Window window) {
-	return window._height;
-}