1 2 module glwt.buffer; 3 4 import cst_ ; 5 6 import derelict.opengl ; 7 8 9 /** Unittest to ensure Compiler works as expected*/ 10 unittest { 11 ArrayBuffer ab; 12 uint au = *(cast(uint*)cast(void*)&ab); 13 assert(ab.id==au, "Error, byte data for Struct is not as expected."); 14 uint bu; 15 ArrayBuffer bb = *(cast(ArrayBuffer*)cast(void*)&bu); 16 assert(bb.id==bu, "Error, byte data for Struct is not as expected."); 17 ArrayBuffer [2] cb; 18 uint [2] cu = cast(uint[])cast(void[])cb; 19 assert(cb[0].id==cu[0], "Error, byte data for Struct is not as expected."); 20 assert(cb[1].id==cu[1], "Error, byte data for Struct is not as expected."); 21 } 22 23 24 /** A wrapper for buffers.*/ 25 struct Buffer(BufferType bufferType) { 26 uint id = 0; 27 static Buffer!bufferType opCall(void[] data, BufferUsage usage) { 28 import std.stdio; 29 bufferType.writeln; 30 Buffer!bufferType buffer; 31 buffer.gen; 32 buffer.bind; 33 buffer.data(data,usage); 34 return buffer; 35 } 36 } 37 alias ArrayBuffer = Buffer!(BufferType.Array ) ; 38 alias AtomicCounterBuffer = Buffer!(BufferType.AtomicCounter ) ; 39 alias CopyReadBuffer = Buffer!(BufferType.CopyRead ) ; 40 alias CopyWriteBuffer = Buffer!(BufferType.CopyWrite ) ; 41 alias DispatchIndirectBuffer = Buffer!(BufferType.DispatchIndirect ) ; 42 alias DrawIndirectBuffer = Buffer!(BufferType.DrawIndirect ) ; 43 alias ElementArrayBuffer = Buffer!(BufferType.ElementArray ) ; 44 alias PixelPackBuffer = Buffer!(BufferType.PixelPack ) ; 45 alias PixelUnpackBuffer = Buffer!(BufferType.PixelUnpack ) ; 46 alias QueryBuffer = Buffer!(BufferType.Query ) ; 47 alias ShaderStorageBuffer = Buffer!(BufferType.ShaderStorage ) ; 48 alias TextureBuffer = Buffer!(BufferType.Texture ) ; 49 alias TransformFeedbackBuffer = Buffer!(BufferType.TransformFeedback ) ; 50 alias UniformBuffer = Buffer!(BufferType.Uniform ) ; 51 52 53 54 55 enum BufferType { 56 Array = GL_ARRAY_BUFFER , 57 AtomicCounter = GL_ATOMIC_COUNTER_BUFFER , 58 CopyRead = GL_COPY_READ_BUFFER , 59 CopyWrite = GL_COPY_WRITE_BUFFER , 60 DispatchIndirect = GL_DISPATCH_INDIRECT_BUFFER , 61 DrawIndirect = GL_DRAW_INDIRECT_BUFFER , 62 ElementArray = GL_ELEMENT_ARRAY_BUFFER , 63 PixelPack = GL_PIXEL_PACK_BUFFER , 64 PixelUnpack = GL_PIXEL_UNPACK_BUFFER , 65 Query = GL_QUERY_BUFFER , 66 ShaderStorage = GL_SHADER_STORAGE_BUFFER , 67 Texture = GL_TEXTURE_BUFFER , 68 TransformFeedback = GL_TRANSFORM_FEEDBACK_BUFFER , 69 Uniform = GL_UNIFORM_BUFFER , 70 } 71 72 73 enum BufferUsage { 74 StreamDraw = GL_STREAM_DRAW , 75 StreamRead = GL_STREAM_READ , 76 StreamCopy = GL_STREAM_COPY , 77 StaticDraw = GL_STATIC_DRAW , 78 StaticRead = GL_STATIC_READ , 79 StaticCopy = GL_STATIC_COPY , 80 DynamicDraw = GL_DYNAMIC_DRAW , 81 DynamicRead = GL_DYNAMIC_READ , 82 DynamicCopy = GL_DYNAMIC_COPY , 83 } 84 85 86 87 88 /** glGenBuffers() wrapper. 89 */ 90 void 91 gen(BufferType bufferType)(ref Buffer!bufferType buffer) 92 { 93 glGenBuffers(1, &buffer.id); 94 } 95 /** glGenBuffers() wrapper. 96 */ 97 void 98 gen(BufferType bufferType)(ref Buffer!bufferType[] buffers) 99 { 100 // Works because a struct with a single var has the same byte data and size as its only var. 101 glGenBuffers(buffers.length, buffers.ptr); 102 } 103 104 105 /** glDeleteBuffers() wrapper. 106 */ 107 void 108 del(BufferType bufferType)(ref Buffer!bufferType buffer) 109 { 110 glDeleteBuffers(1, &buffer.id); 111 } 112 113 114 115 116 117 118 119 120 enum string buffer_ensureGen_m = "version(assert){assert(buffer.id!=0, \"Buffer not generated. Call `buffer.gen` before using this function.\");}"; 121 enum string buffer_ensureBound_m = buffer_ensureGen_m~"version(assert){ 122 static if(is(typeof(buffer)==ArrayBuffer)) { 123 uint bb;//bound buffer 124 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, cast(int*)&bb); 125 assert(buffer.id==bb, \"Buffer not bound. Call `buffer.bind` before using this function.\"); 126 } 127 else { 128 pragma(msg, \"No test for this buffer being bound (currently), be sure it is (to bind call `bind` method).\"); 129 }}"; 130 131 132 133 134 135 136 /** glBindBuffer() wrapper. 137 Binds buffer to be used by future calls. 138 */ 139 void 140 bind(BufferType bufferType)(Buffer!bufferType buffer) 141 { 142 mixin(buffer_ensureGen_m); 143 glBindBuffer(bufferType, buffer.id); 144 } 145 /**ditto*/ 146 alias use=bind; 147 148 149 150 151 152 153 /** glBufferData() wrapper. 154 Sets the buffer's data. 155 */ 156 void 157 data(BufferType bufferType)(Buffer!bufferType buffer, void[] data, BufferUsage usage) 158 { 159 mixin(buffer_ensureBound_m); 160 glBufferData(bufferType, data.length, data.ptr, usage); 161 } 162 163 164 165 /** body() wrapper. 166 Sets the buffer's sub data. 167 */ 168 void 169 subData(BufferType bufferType)(Buffer!bufferType buffer, void[] data, size_t offset) 170 { 171 mixin(buffer_ensureBound_m); 172 glBufferSubData(bufferType, offset, data.length, data.ptr); 173 } 174 175 176 177 /** glGetBufferSubData() wrapper. 178 Gets the buffer's sub data. 179 */ 180 void 181 getSubData(BufferType bufferType)(Buffer!bufferType buffer, void* data, size_t offset, size_t length) 182 { 183 mixin(buffer_ensureBound_m); 184 glGetBufferSubData(bufferType, offset, length, data); 185 }