mirror of
https://github.com/love2d/love.git
synced 2026-08-18 11:44:15 +02:00
Merge branch '12.0-development' into metal
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "graphics/Buffer.h"
|
||||
#include "Metal.h"
|
||||
#include "common/Range.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -37,23 +38,21 @@ public:
|
||||
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);
|
||||
virtual ~Buffer();
|
||||
|
||||
void *map() override;
|
||||
void unmap() override;
|
||||
void setMappedRangeModified(size_t offset, size_t size) override;
|
||||
void *map(MapType map, size_t offset, size_t size) override;
|
||||
void unmap(size_t usedoffset, size_t usedsize) 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 (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;
|
||||
id<MTLBuffer> mapBuffer;
|
||||
|
||||
NSRange mappedRange;
|
||||
Range mappedRange;
|
||||
|
||||
}; // Buffer
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
**/
|
||||
|
||||
#import "Buffer.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -58,12 +59,13 @@ static MTLPixelFormat getMTLPixelFormat(DataFormat format)
|
||||
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)
|
||||
, mapBuffer(nil)
|
||||
, mappedRange()
|
||||
{ @autoreleasepool {
|
||||
size = getSize();
|
||||
arraylength = getArrayLength();
|
||||
|
||||
MTLResourceOptions opts = MTLResourceStorageModeManaged;
|
||||
MTLResourceOptions opts = MTLResourceStorageModePrivate;
|
||||
buffer = [device newBufferWithLength:size options:opts];
|
||||
|
||||
if (buffer == nil)
|
||||
@@ -71,25 +73,22 @@ Buffer::Buffer(love::graphics::Graphics *gfx, id<MTLDevice> device, const Settin
|
||||
|
||||
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 (@available(iOS 12, macOS 10.14, *))
|
||||
{
|
||||
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;
|
||||
|
||||
if (data != nullptr)
|
||||
{
|
||||
memcpy(map(), data, size);
|
||||
unmap();
|
||||
}
|
||||
fill(0, size, data);
|
||||
}}
|
||||
|
||||
Buffer::~Buffer()
|
||||
@@ -98,30 +97,77 @@ Buffer::~Buffer()
|
||||
texture = nil;
|
||||
}}
|
||||
|
||||
void *Buffer::map()
|
||||
{
|
||||
return memoryMap;
|
||||
}
|
||||
|
||||
void Buffer::unmap()
|
||||
void *Buffer::map(MapType /*map*/, size_t offset, size_t size)
|
||||
{ @autoreleasepool {
|
||||
[buffer didModifyRange:{0, size}];
|
||||
if (size == 0)
|
||||
return nullptr;
|
||||
|
||||
Range r(offset, size);
|
||||
|
||||
if (!Range(0, getSize()).contains(r))
|
||||
return nullptr;
|
||||
|
||||
auto gfx = Graphics::getInstance();
|
||||
|
||||
// TODO: Don't create a new buffer every time, also do something for stream
|
||||
// buffers.
|
||||
mapBuffer = [gfx->device newBufferWithLength:size options:MTLResourceStorageModeShared];
|
||||
|
||||
if (mapBuffer != nil)
|
||||
{
|
||||
mappedRange = r;
|
||||
return mapBuffer.contents;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}}
|
||||
|
||||
void Buffer::setMappedRangeModified(size_t offset, size_t size)
|
||||
{
|
||||
mappedRange = NSIntersectionRange(mappedRange, {offset, size});
|
||||
}
|
||||
void Buffer::unmap(size_t usedoffset, size_t usedsize)
|
||||
{ @autoreleasepool {
|
||||
if (mapBuffer == nil)
|
||||
return;
|
||||
|
||||
Range r(usedoffset, usedsize);
|
||||
|
||||
if (!mapped || !mappedRange.contains(r))
|
||||
return;
|
||||
|
||||
auto gfx = Graphics::getInstance();
|
||||
auto encoder = gfx->useBlitEncoder();
|
||||
|
||||
[encoder copyFromBuffer:mapBuffer
|
||||
sourceOffset:(usedoffset - mappedRange.getOffset())
|
||||
toBuffer:buffer
|
||||
destinationOffset:usedoffset
|
||||
size:usedsize];
|
||||
|
||||
mapBuffer = nil;
|
||||
}}
|
||||
|
||||
void Buffer::fill(size_t offset, size_t size, const void *data)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
{ @autoreleasepool {
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
void Buffer::copyTo(size_t offset, size_t size, love::graphics::Buffer *other, size_t otheroffset)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
size_t buffersize = getSize();
|
||||
|
||||
if (!Range(0, buffersize).contains(Range(offset, size)))
|
||||
return;
|
||||
|
||||
// TODO: Don't create a new buffer every time, also do something for stream
|
||||
// buffers.
|
||||
auto gfx = Graphics::getInstance();
|
||||
auto encoder = gfx->useBlitEncoder();
|
||||
|
||||
auto tempbuffer = [gfx->device newBufferWithLength:size options:MTLResourceStorageModeShared];
|
||||
memcpy(tempbuffer.contents, data, size);
|
||||
|
||||
[encoder copyFromBuffer:tempbuffer
|
||||
sourceOffset:0
|
||||
toBuffer:buffer
|
||||
destinationOffset:offset
|
||||
size:size];
|
||||
}}
|
||||
|
||||
} // metal
|
||||
} // graphics
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
love::graphics::Buffer *newBuffer(const Buffer::Settings &settings, const std::vector<Buffer::DataDeclaration> &format, const void *data, size_t size, size_t arraylength) override;
|
||||
|
||||
void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
|
||||
bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, int backbufferdepth) override;
|
||||
bool setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa) override;
|
||||
void unSetMode() override;
|
||||
|
||||
void setActive(bool active) override;
|
||||
@@ -65,6 +65,9 @@ public:
|
||||
|
||||
void present(void *screenshotCallbackData) override;
|
||||
|
||||
int getRequestedBackbufferMSAA() const override { return 0; } // TODO
|
||||
int getBackbufferMSAA() const override { return 0; } // TODO
|
||||
|
||||
void setColor(Colorf c) override;
|
||||
|
||||
void setScissor(const Rect &rect) override;
|
||||
|
||||
@@ -188,7 +188,8 @@ Graphics::Graphics()
|
||||
{0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{0, 0, 0, 1},
|
||||
};
|
||||
Buffer::Settings attribsettings(Buffer::TYPEFLAG_VERTEX, 0, BUFFERUSAGE_STATIC);
|
||||
|
||||
Buffer::Settings attribsettings(Buffer::TYPEFLAG_VERTEX, BUFFERUSAGE_STATIC);
|
||||
|
||||
defaultAttributesBuffer = newBuffer(attribsettings, dataformat, &defaults, sizeof(DefaultVertexAttributes), 0);
|
||||
}
|
||||
@@ -288,13 +289,13 @@ void Graphics::setViewportSize(int width, int height, int pixelwidth, int pixelh
|
||||
}
|
||||
}
|
||||
|
||||
bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, int backbufferdepth)
|
||||
bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool windowhasstencil, int msaa)
|
||||
{ @autoreleasepool {
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->metalLayer = (__bridge CAMetalLayer *) context;
|
||||
|
||||
this->windowHasStencil = backbufferstencil;
|
||||
this->windowHasStencil = windowhasstencil;
|
||||
|
||||
metalLayer.device = device;
|
||||
metalLayer.pixelFormat = isGammaCorrect() ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm;
|
||||
|
||||
@@ -40,8 +40,6 @@ public:
|
||||
Texture(love::graphics::Graphics *gfx, id<MTLDevice> device, const Settings &settings, const Slices *data);
|
||||
virtual ~Texture();
|
||||
|
||||
void generateMipmaps() override;
|
||||
love::image::ImageData *newImageData(love::image::Image *module, int slice, int mipmap, const Rect &rect) override;
|
||||
void setSamplerState(const SamplerState &s) override;
|
||||
|
||||
ptrdiff_t getHandle() const override { return (ptrdiff_t) texture; }
|
||||
@@ -54,6 +52,8 @@ public:
|
||||
private:
|
||||
|
||||
void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r, love::image::ImageDataBase *imgd = nullptr) override;
|
||||
void generateMipmapsInternal() override;
|
||||
void readbackImageData(love::image::ImageData *imagedata, int slice, int mipmap, const Rect &rect) override;
|
||||
|
||||
id<MTLTexture> texture;
|
||||
id<MTLTexture> msaaTexture;
|
||||
|
||||
@@ -197,7 +197,7 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s
|
||||
options:options];
|
||||
}}
|
||||
|
||||
void Texture::generateMipmaps()
|
||||
void Texture::generateMipmapsInternal()
|
||||
{ @autoreleasepool {
|
||||
// TODO: alternate method for non-color-renderable and non-filterable
|
||||
// pixel formats.
|
||||
@@ -205,10 +205,9 @@ void Texture::generateMipmaps()
|
||||
[encoder generateMipmapsForTexture:texture];
|
||||
}}
|
||||
|
||||
love::image::ImageData *Texture::newImageData(love::image::Image *module, int slice, int mipmap, const Rect &rect)
|
||||
void Texture::readbackImageData(love::image::ImageData *imagedata, int slice, int mipmap, const Rect &rect)
|
||||
{
|
||||
// TODO
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Texture::setSamplerState(const SamplerState &s)
|
||||
|
||||
Reference in New Issue
Block a user