Browse Source

metal: initial texel buffer implementation

Alex Szpakowski 5 years ago
parent
commit
a8c879f3bf
2 changed files with 51 additions and 1 deletions
  1. 3 1
      src/modules/graphics/metal/Buffer.h
  2. 48 0
      src/modules/graphics/metal/Buffer.mm

+ 3 - 1
src/modules/graphics/metal/Buffer.h

@@ -42,13 +42,15 @@ public:
 	void setMappedRangeModified(size_t offset, size_t size) override;
 	void fill(size_t offset, size_t size, const void *data) override;
 	ptrdiff_t getHandle() const override { return (ptrdiff_t) buffer; }
-	ptrdiff_t getTexelBufferHandle() const override { return 0; }
+	ptrdiff_t getTexelBufferHandle() const override { return (ptrdiff_t) texture; }
 
 	void copyTo(size_t offset, size_t size, love::graphics::Buffer *other, size_t otheroffset) override;
 
 private:
 
 	id<MTLBuffer> buffer;
+	id<MTLTexture> texture;
+
 	char *memoryMap;
 
 	NSRange mappedRange;

+ 48 - 0
src/modules/graphics/metal/Buffer.mm

@@ -27,13 +27,61 @@ namespace graphics
 namespace metal
 {
 
+static MTLPixelFormat getMTLPixelFormat(DataFormat format)
+{
+	switch (format)
+	{
+		case DATAFORMAT_FLOAT: return MTLPixelFormatR32Float;
+		case DATAFORMAT_FLOAT_VEC2: return MTLPixelFormatRG32Float;
+		case DATAFORMAT_FLOAT_VEC4: return MTLPixelFormatRGBA32Float;
+		case DATAFORMAT_INT32: return MTLPixelFormatR32Sint;
+		case DATAFORMAT_INT32_VEC2: return MTLPixelFormatRG32Sint;
+		case DATAFORMAT_INT32_VEC4: return MTLPixelFormatRGBA32Sint;
+		case DATAFORMAT_UINT32: return MTLPixelFormatR32Uint;
+		case DATAFORMAT_UINT32_VEC2: return MTLPixelFormatRG32Uint;
+		case DATAFORMAT_UINT32_VEC4: return MTLPixelFormatRGBA32Uint;
+		case DATAFORMAT_UNORM8_VEC4: return MTLPixelFormatRGBA8Unorm;
+		case DATAFORMAT_SNORM8_VEC4: return MTLPixelFormatRGBA8Snorm;
+		case DATAFORMAT_INT8_VEC4: return MTLPixelFormatRGBA8Sint;
+		case DATAFORMAT_UINT8_VEC4: return MTLPixelFormatRGBA8Uint;
+		case DATAFORMAT_UNORM16_VEC2: return MTLPixelFormatRG16Unorm;
+		case DATAFORMAT_UNORM16_VEC4: return MTLPixelFormatRGBA16Unorm;
+		case DATAFORMAT_INT16_VEC2: return MTLPixelFormatRG16Sint;
+		case DATAFORMAT_INT16_VEC4: return MTLPixelFormatRGBA16Sint;
+		case DATAFORMAT_UINT16: return MTLPixelFormatR16Uint;
+		case DATAFORMAT_UINT16_VEC2: return MTLPixelFormatRG16Uint;
+		case DATAFORMAT_UINT16_VEC4: return MTLPixelFormatRGBA16Uint;
+		default: return MTLPixelFormatInvalid;
+	}
+}
+
 Buffer::Buffer(love::graphics::Graphics *gfx, id<MTLDevice> device, const Settings &settings, const std::vector<DataDeclaration> &format, const void *data, size_t size, size_t arraylength)
 	: love::graphics::Buffer(gfx, settings, format, size, arraylength)
+	, texture(nil)
 	, mappedRange()
 { @autoreleasepool {
+	size = getSize();
+	arraylength = getArrayLength();
+
 	MTLResourceOptions opts = MTLResourceStorageModeManaged;
 	buffer = [device newBufferWithLength:size options:opts];
 
+	if (buffer == nil)
+		throw love::Exception("Could not create buffer (out of VRAM?)");
+
+	if (typeFlags & TYPEFLAG_TEXEL)
+	{
+		MTLPixelFormat pixformat = getMTLPixelFormat(getDataMember(0).decl.format);
+		auto desc = [MTLTextureDescriptor textureBufferDescriptorWithPixelFormat:pixformat
+																		   width:size
+																 resourceOptions:opts
+																		   usage:MTLTextureUsageShaderRead];
+		texture = [buffer newTextureWithDescriptor:desc offset:0 bytesPerRow:size];
+
+		if (texture == nil)
+			throw love::Exception("Could not create Metal texel buffer.");
+	}
+
 	// TODO: synchronization etc
 	memoryMap = (char *) buffer.contents;