1 module sbylib.graphics.wrapper.buffer; 2 3 import std; 4 import sbylib.wrapper.vulkan; 5 import sbylib.graphics.wrapper.device; 6 import sbylib.graphics.util.own; 7 8 class VBuffer(T) { 9 10 alias Type = T; 11 12 private { 13 @own { 14 Buffer _buffer; 15 DeviceMemory _memory; 16 } 17 size_t size; 18 } 19 20 mixin ImplReleaseOwn; 21 22 this(const T[] data, BufferUsage usage) { 23 this(T.sizeof * data.length, usage, MemoryProperties.MemoryType.Flags.HostVisible); 24 this.write(data); 25 } 26 27 this(size_t size, BufferUsage usage, MemoryProperties.MemoryType.Flags flag) { 28 this.size = size; 29 30 with (VDevice()) { 31 Buffer.CreateInfo bufferInfo = { 32 usage: usage, 33 size: size, 34 sharingMode: SharingMode.Exclusive, 35 }; 36 this._buffer = new Buffer(device, bufferInfo); 37 this._memory = _buffer.allocateMemory(gpu, flag); 38 39 _memory.bindBuffer(_buffer, 0); 40 } 41 } 42 43 Buffer buffer() { 44 return _buffer; 45 } 46 47 DeviceMemory memory() { 48 return _memory; 49 } 50 51 auto map() { 52 struct HostMemory { 53 private DeviceMemory deviceMemory; 54 T[] hostMemory; 55 56 ~this() { 57 deviceMemory.unmap(); 58 } 59 60 static if (isAggregateType!(T)) { 61 static foreach (mem; __traits(allMembers, T)) { 62 static if (!isCallable!(__traits(getMember, T, mem))) { 63 mixin(q{ 64 auto ref ${mem} () { 65 return hostMemory[0].${mem}; 66 } 67 }.replace("${mem}", mem)); 68 } 69 } 70 } 71 } 72 73 return HostMemory(this.memory, cast(T[])this.memory.map(0, this.size, 0)); 74 } 75 76 void write(const T[] data) { 77 auto hostMemory = memory.map(0, T.sizeof * data.length, 0); 78 hostMemory[] = (cast(const ubyte[])data)[]; 79 memory.unmap(); 80 } 81 }