|
@@ -112,6 +112,21 @@ static MTLStencilOperation getMTLStencilOperation(StencilAction action)
|
|
return MTLStencilOperationKeep;
|
|
return MTLStencilOperationKeep;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline id<MTLTexture> getMTLTexture(love::graphics::Texture *tex)
|
|
|
|
+{
|
|
|
|
+ return tex ? (__bridge id<MTLTexture>)(void *) tex->getHandle() : nil;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline id<MTLTexture> getMTLRenderTarget(love::graphics::Texture *tex)
|
|
|
|
+{
|
|
|
|
+ return tex ? (__bridge id<MTLTexture>)(void *) tex->getRenderTargetHandle() : nil;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline id<MTLBuffer> getMTLBuffer(love::graphics::Resource *res)
|
|
|
|
+{
|
|
|
|
+ return res ? (__bridge id<MTLBuffer>)(void *) res->getHandle() : nil;
|
|
|
|
+}
|
|
|
|
+
|
|
love::graphics::Graphics *createInstance()
|
|
love::graphics::Graphics *createInstance()
|
|
{
|
|
{
|
|
love::graphics::Graphics *instance = nullptr;
|
|
love::graphics::Graphics *instance = nullptr;
|
|
@@ -190,7 +205,7 @@ Graphics::Graphics()
|
|
window->windowToDPICoords(&dpiW, &dpiH);
|
|
window->windowToDPICoords(&dpiW, &dpiH);
|
|
|
|
|
|
void *context = nullptr; // TODO
|
|
void *context = nullptr; // TODO
|
|
- setMode(context, (int) dpiW, (int) dpiH, window->getPixelWidth(), window->getPixelHeight(), settings.stencil);
|
|
|
|
|
|
+ setMode(context, (int) dpiW, (int) dpiH, window->getPixelWidth(), window->getPixelHeight(), settings.stencil, settings.depth);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}}
|
|
}}
|
|
@@ -257,18 +272,18 @@ 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 windowhasstencil)
|
|
|
|
|
|
+bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int pixelheight, bool backbufferstencil, int backbufferdepth)
|
|
{ @autoreleasepool {
|
|
{ @autoreleasepool {
|
|
this->width = width;
|
|
this->width = width;
|
|
this->height = height;
|
|
this->height = height;
|
|
this->metalLayer = (__bridge CAMetalLayer *) context;
|
|
this->metalLayer = (__bridge CAMetalLayer *) context;
|
|
|
|
|
|
- this->windowHasStencil = windowhasstencil;
|
|
|
|
|
|
+ this->windowHasStencil = backbufferstencil;
|
|
|
|
|
|
metalLayer.device = device;
|
|
metalLayer.device = device;
|
|
metalLayer.pixelFormat = isGammaCorrect() ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm;
|
|
metalLayer.pixelFormat = isGammaCorrect() ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm;
|
|
|
|
|
|
- // TODO: set to NO when we have pending screen captures
|
|
|
|
|
|
+ // This is set to NO when there are pending screen captures.
|
|
metalLayer.framebufferOnly = YES;
|
|
metalLayer.framebufferOnly = YES;
|
|
|
|
|
|
setViewportSize(width, height, pixelwidth, pixelheight);
|
|
setViewportSize(width, height, pixelwidth, pixelheight);
|
|
@@ -338,8 +353,17 @@ void Graphics::setActive(bool enable)
|
|
id<MTLCommandBuffer> Graphics::useCommandBuffer()
|
|
id<MTLCommandBuffer> Graphics::useCommandBuffer()
|
|
{
|
|
{
|
|
if (commandBuffer == nil)
|
|
if (commandBuffer == nil)
|
|
|
|
+ {
|
|
commandBuffer = [commandQueue commandBuffer];
|
|
commandBuffer = [commandQueue commandBuffer];
|
|
|
|
|
|
|
|
+ Graphics *pthis = this;
|
|
|
|
+ pthis->retain();
|
|
|
|
+ [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull) {
|
|
|
|
+ pthis->completeCommandBufferIndex.fetch_add(1, std::memory_order_relaxed);
|
|
|
|
+ pthis->release();
|
|
|
|
+ }];
|
|
|
|
+ }
|
|
|
|
+
|
|
return commandBuffer;
|
|
return commandBuffer;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -361,21 +385,30 @@ id<MTLRenderCommandEncoder> Graphics::useRenderEncoder()
|
|
{
|
|
{
|
|
submitBlitEncoder();
|
|
submitBlitEncoder();
|
|
|
|
|
|
|
|
+ // Pass desc info for non-backbuffer render targets are set up in
|
|
|
|
+ // setRenderTagetsInternal.
|
|
const auto &rts = states.back().renderTargets;
|
|
const auto &rts = states.back().renderTargets;
|
|
- if (rts.getFirstTarget().texture.get() != nullptr)
|
|
|
|
- {
|
|
|
|
- // TODO
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
|
|
+ if (rts.getFirstTarget().texture.get() == nullptr)
|
|
{
|
|
{
|
|
if (activeDrawable == nil)
|
|
if (activeDrawable == nil)
|
|
|
|
+ {
|
|
|
|
+ // This is reset to YES after each frame.
|
|
|
|
+ // TODO: Does setting this reallocate memory?
|
|
|
|
+ if (!pendingScreenshotCallbacks.empty())
|
|
|
|
+ metalLayer.framebufferOnly = NO;
|
|
|
|
+
|
|
activeDrawable = [metalLayer nextDrawable];
|
|
activeDrawable = [metalLayer nextDrawable];
|
|
|
|
+ }
|
|
|
|
+
|
|
passDesc.colorAttachments[0].texture = activeDrawable.texture;
|
|
passDesc.colorAttachments[0].texture = activeDrawable.texture;
|
|
|
|
+ passDesc.colorAttachments[0].level = 0;
|
|
|
|
+ passDesc.colorAttachments[0].slice = 0;
|
|
|
|
+ passDesc.colorAttachments[0].depthPlane = 0;
|
|
}
|
|
}
|
|
|
|
|
|
renderEncoder = [useCommandBuffer() renderCommandEncoderWithDescriptor:passDesc];
|
|
renderEncoder = [useCommandBuffer() renderCommandEncoderWithDescriptor:passDesc];
|
|
|
|
|
|
- id<MTLBuffer> defaultbuffer = (__bridge id<MTLBuffer>)(void *)defaultAttributesBuffer->getHandle();
|
|
|
|
|
|
+ id<MTLBuffer> defaultbuffer = getMTLBuffer(defaultAttributesBuffer);
|
|
[renderEncoder setVertexBuffer:defaultbuffer offset:0 atIndex:DEFAULT_VERTEX_BUFFER_BINDING];
|
|
[renderEncoder setVertexBuffer:defaultbuffer offset:0 atIndex:DEFAULT_VERTEX_BUFFER_BINDING];
|
|
|
|
|
|
dirtyRenderState = STATEBIT_ALL;
|
|
dirtyRenderState = STATEBIT_ALL;
|
|
@@ -622,37 +655,33 @@ void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, lo
|
|
size_t alignment = 16;
|
|
size_t alignment = 16;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- // TODO: use the size of all uniforms
|
|
|
|
- size_t size = sizeof(Shader::BuiltinUniformData);
|
|
|
|
|
|
+ size_t size = s->getLocalUniformBufferSize();
|
|
|
|
+ uint8 *bufferdata = s->getLocalUniformBufferData();
|
|
|
|
|
|
- Shader::BuiltinUniformData data;
|
|
|
|
|
|
+ auto builtins = (Shader::BuiltinUniformData *) (bufferdata + s->getBuiltinUniformDataOffset());
|
|
|
|
|
|
- data.transformMatrix = getTransform();
|
|
|
|
- data.projectionMatrix = getProjection();
|
|
|
|
|
|
+ builtins->transformMatrix = getTransform();
|
|
|
|
+ builtins->projectionMatrix = getProjection();
|
|
|
|
|
|
// The normal matrix is the transpose of the inverse of the rotation portion
|
|
// The normal matrix is the transpose of the inverse of the rotation portion
|
|
// (top-left 3x3) of the transform matrix.
|
|
// (top-left 3x3) of the transform matrix.
|
|
{
|
|
{
|
|
- Matrix3 normalmatrix = Matrix3(data.transformMatrix).transposedInverse();
|
|
|
|
|
|
+ Matrix3 normalmatrix = Matrix3(builtins->transformMatrix).transposedInverse();
|
|
const float *e = normalmatrix.getElements();
|
|
const float *e = normalmatrix.getElements();
|
|
for (int i = 0; i < 3; i++)
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
{
|
|
- data.normalMatrix[i].x = e[i * 3 + 0];
|
|
|
|
- data.normalMatrix[i].y = e[i * 3 + 1];
|
|
|
|
- data.normalMatrix[i].z = e[i * 3 + 2];
|
|
|
|
- data.normalMatrix[i].w = 0.0f;
|
|
|
|
|
|
+ builtins->normalMatrix[i].x = e[i * 3 + 0];
|
|
|
|
+ builtins->normalMatrix[i].y = e[i * 3 + 1];
|
|
|
|
+ builtins->normalMatrix[i].z = e[i * 3 + 2];
|
|
|
|
+ builtins->normalMatrix[i].w = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// FIXME: should be active RT dimensions
|
|
// FIXME: should be active RT dimensions
|
|
- data.screenSizeParams.x = getPixelWidth();
|
|
|
|
- data.screenSizeParams.y = getPixelHeight();
|
|
|
|
|
|
+ builtins->screenSizeParams = Vector4(getPixelWidth(), getPixelHeight(), 1.0f, 0.0f);
|
|
|
|
|
|
- data.screenSizeParams.z = 1.0f;
|
|
|
|
- data.screenSizeParams.w = 0.0f;
|
|
|
|
-
|
|
|
|
- data.constantColor = getColor();
|
|
|
|
- gammaCorrectColor(data.constantColor);
|
|
|
|
|
|
+ builtins->constantColor = getColor();
|
|
|
|
+ gammaCorrectColor(builtins->constantColor);
|
|
|
|
|
|
if (uniformBuffer->getSize() < uniformBufferOffset + size)
|
|
if (uniformBuffer->getSize() < uniformBufferOffset + size)
|
|
{
|
|
{
|
|
@@ -666,9 +695,9 @@ void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, lo
|
|
if (uniformBufferData.data == nullptr)
|
|
if (uniformBufferData.data == nullptr)
|
|
uniformBufferData = uniformBuffer->map(uniformBuffer->getSize());
|
|
uniformBufferData = uniformBuffer->map(uniformBuffer->getSize());
|
|
|
|
|
|
- memcpy(uniformBufferData.data + uniformBufferOffset, &data, sizeof(Shader::BuiltinUniformData));
|
|
|
|
|
|
+ memcpy(uniformBufferData.data + uniformBufferOffset, bufferdata, size);
|
|
|
|
|
|
- id<MTLBuffer> buffer = (__bridge id<MTLBuffer>)(void *)uniformBuffer->getHandle();
|
|
|
|
|
|
+ id<MTLBuffer> buffer = getMTLBuffer(uniformBuffer);
|
|
int index = Shader::getUniformBufferBinding();
|
|
int index = Shader::getUniformBufferBinding();
|
|
|
|
|
|
// TODO: bind shader textures/samplers
|
|
// TODO: bind shader textures/samplers
|
|
@@ -679,6 +708,26 @@ void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, lo
|
|
uniformBufferOffset += alignUp(size, alignment);
|
|
uniformBufferOffset += alignUp(size, alignment);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void setVertexBuffers(id<MTLRenderCommandEncoder> encoder, const BufferBindings *buffers)
|
|
|
|
+{
|
|
|
|
+ uint32 allbits = buffers->useBits;
|
|
|
|
+ uint32 i = 0;
|
|
|
|
+ while (allbits)
|
|
|
|
+ {
|
|
|
|
+ uint32 bit = 1u << i;
|
|
|
|
+
|
|
|
|
+ if (buffers->useBits & bit)
|
|
|
|
+ {
|
|
|
|
+ auto b = buffers->info[i];
|
|
|
|
+ id<MTLBuffer> buffer = getMTLBuffer(b.buffer);
|
|
|
|
+ [encoder setVertexBuffer:buffer offset:b.offset atIndex:i + VERTEX_BUFFER_BINDING_START];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ i++;
|
|
|
|
+ allbits >>= 1;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void Graphics::draw(const DrawCommand &cmd)
|
|
void Graphics::draw(const DrawCommand &cmd)
|
|
{ @autoreleasepool {
|
|
{ @autoreleasepool {
|
|
id<MTLRenderCommandEncoder> encoder = useRenderEncoder();
|
|
id<MTLRenderCommandEncoder> encoder = useRenderEncoder();
|
|
@@ -690,29 +739,14 @@ void Graphics::draw(const DrawCommand &cmd)
|
|
if (texture == nullptr)
|
|
if (texture == nullptr)
|
|
texture = defaultTextures[TEXTURE_2D];
|
|
texture = defaultTextures[TEXTURE_2D];
|
|
|
|
|
|
- id<MTLTexture> mtltexture = (__bridge id<MTLTexture>)(void *) texture->getHandle();
|
|
|
|
|
|
+ id<MTLTexture> mtltexture = getMTLTexture(texture);
|
|
|
|
|
|
[encoder setFragmentTexture:mtltexture atIndex:0];
|
|
[encoder setFragmentTexture:mtltexture atIndex:0];
|
|
[encoder setFragmentSamplerState:((Texture *)texture)->getMTLSampler() atIndex:0];
|
|
[encoder setFragmentSamplerState:((Texture *)texture)->getMTLSampler() atIndex:0];
|
|
|
|
|
|
[encoder setCullMode:MTLCullModeNone];
|
|
[encoder setCullMode:MTLCullModeNone];
|
|
|
|
|
|
- uint32 allbits = cmd.buffers->useBits;
|
|
|
|
- uint32 i = 0;
|
|
|
|
- while (allbits)
|
|
|
|
- {
|
|
|
|
- uint32 bit = 1u << i;
|
|
|
|
-
|
|
|
|
- if (cmd.buffers->useBits & bit)
|
|
|
|
- {
|
|
|
|
- auto b = cmd.buffers->info[i];
|
|
|
|
- id<MTLBuffer> buffer = (__bridge id<MTLBuffer>)(void *)b.buffer->getHandle();
|
|
|
|
- [encoder setVertexBuffer:buffer offset:b.offset atIndex:i + VERTEX_BUFFER_BINDING_START];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- i++;
|
|
|
|
- allbits >>= 1;
|
|
|
|
- }
|
|
|
|
|
|
+ setVertexBuffers(encoder, cmd.buffers);
|
|
|
|
|
|
[encoder drawPrimitives:MTLPrimitiveTypeTriangle
|
|
[encoder drawPrimitives:MTLPrimitiveTypeTriangle
|
|
vertexStart:cmd.vertexStart
|
|
vertexStart:cmd.vertexStart
|
|
@@ -731,36 +765,21 @@ void Graphics::draw(const DrawIndexedCommand &cmd)
|
|
if (texture == nullptr)
|
|
if (texture == nullptr)
|
|
texture = defaultTextures[TEXTURE_2D];
|
|
texture = defaultTextures[TEXTURE_2D];
|
|
|
|
|
|
- id<MTLTexture> mtltexture = (__bridge id<MTLTexture>)(void *) texture->getHandle();
|
|
|
|
|
|
+ id<MTLTexture> mtltexture = getMTLTexture(texture);
|
|
|
|
|
|
[encoder setFragmentTexture:mtltexture atIndex:0];
|
|
[encoder setFragmentTexture:mtltexture atIndex:0];
|
|
[encoder setFragmentSamplerState:((Texture *)texture)->getMTLSampler() atIndex:0];
|
|
[encoder setFragmentSamplerState:((Texture *)texture)->getMTLSampler() atIndex:0];
|
|
|
|
|
|
[encoder setCullMode:MTLCullModeNone];
|
|
[encoder setCullMode:MTLCullModeNone];
|
|
|
|
|
|
- uint32 allbits = cmd.buffers->useBits;
|
|
|
|
- uint32 i = 0;
|
|
|
|
- while (allbits)
|
|
|
|
- {
|
|
|
|
- uint32 bit = 1u << i;
|
|
|
|
-
|
|
|
|
- if (cmd.buffers->useBits & bit)
|
|
|
|
- {
|
|
|
|
- auto b = cmd.buffers->info[i];
|
|
|
|
- id<MTLBuffer> buffer = (__bridge id<MTLBuffer>)(void *)b.buffer->getHandle();
|
|
|
|
- [encoder setVertexBuffer:buffer offset:b.offset atIndex:i + VERTEX_BUFFER_BINDING_START];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- i++;
|
|
|
|
- allbits >>= 1;
|
|
|
|
- }
|
|
|
|
|
|
+ setVertexBuffers(encoder, cmd.buffers);
|
|
|
|
|
|
auto indexType = cmd.indexType == INDEX_UINT32 ? MTLIndexTypeUInt32 : MTLIndexTypeUInt16;
|
|
auto indexType = cmd.indexType == INDEX_UINT32 ? MTLIndexTypeUInt32 : MTLIndexTypeUInt16;
|
|
|
|
|
|
[encoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
|
[encoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
|
indexCount:cmd.indexCount
|
|
indexCount:cmd.indexCount
|
|
indexType:indexType
|
|
indexType:indexType
|
|
- indexBuffer:(__bridge id<MTLBuffer>)(void*)cmd.indexBuffer->getHandle()
|
|
|
|
|
|
+ indexBuffer:getMTLBuffer(cmd.indexBuffer)
|
|
indexBufferOffset:cmd.indexBufferOffset
|
|
indexBufferOffset:cmd.indexBufferOffset
|
|
instanceCount:cmd.instanceCount];
|
|
instanceCount:cmd.instanceCount];
|
|
}}
|
|
}}
|
|
@@ -778,31 +797,16 @@ void Graphics::drawQuads(int start, int count, const VertexAttributes &attribute
|
|
if (texture == nullptr)
|
|
if (texture == nullptr)
|
|
texture = defaultTextures[TEXTURE_2D];
|
|
texture = defaultTextures[TEXTURE_2D];
|
|
|
|
|
|
- id<MTLTexture> mtltexture = (__bridge id<MTLTexture>)(void *) texture->getHandle();
|
|
|
|
|
|
+ id<MTLTexture> mtltexture = getMTLTexture(texture);
|
|
|
|
|
|
[encoder setFragmentTexture:mtltexture atIndex:0];
|
|
[encoder setFragmentTexture:mtltexture atIndex:0];
|
|
[encoder setFragmentSamplerState:((Texture *)texture)->getMTLSampler() atIndex:0];
|
|
[encoder setFragmentSamplerState:((Texture *)texture)->getMTLSampler() atIndex:0];
|
|
|
|
|
|
[encoder setCullMode:MTLCullModeNone];
|
|
[encoder setCullMode:MTLCullModeNone];
|
|
|
|
|
|
- uint32 allbits = buffers.useBits;
|
|
|
|
- uint32 i = 0;
|
|
|
|
- while (allbits)
|
|
|
|
- {
|
|
|
|
- uint32 bit = 1u << i;
|
|
|
|
-
|
|
|
|
- if (buffers.useBits & bit)
|
|
|
|
- {
|
|
|
|
- auto b = buffers.info[i];
|
|
|
|
- id<MTLBuffer> buffer = (__bridge id<MTLBuffer>)(void *)b.buffer->getHandle();
|
|
|
|
- [encoder setVertexBuffer:buffer offset:b.offset atIndex:i + VERTEX_BUFFER_BINDING_START];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- i++;
|
|
|
|
- allbits >>= 1;
|
|
|
|
- }
|
|
|
|
|
|
+ setVertexBuffers(encoder, &buffers);
|
|
|
|
|
|
- id<MTLBuffer> ib = (__bridge id<MTLBuffer>)(void *) quadIndexBuffer->getHandle();
|
|
|
|
|
|
+ id<MTLBuffer> ib = getMTLBuffer(quadIndexBuffer);
|
|
|
|
|
|
// TODO: support for iOS devices that don't support base vertex.
|
|
// TODO: support for iOS devices that don't support base vertex.
|
|
|
|
|
|
@@ -827,56 +831,60 @@ void Graphics::drawQuads(int start, int count, const VertexAttributes &attribute
|
|
}
|
|
}
|
|
}}
|
|
}}
|
|
|
|
|
|
-void Graphics::setRenderTargetsInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBcanvas)
|
|
|
|
-{ @autoreleasepool {
|
|
|
|
- const DisplayState &state = states.back();
|
|
|
|
-
|
|
|
|
- endPass();
|
|
|
|
-
|
|
|
|
- for (size_t i = 0; i < rts.colors.size(); i++)
|
|
|
|
- {
|
|
|
|
- auto rt = rts.colors[i];
|
|
|
|
- auto tex = rt.texture;
|
|
|
|
- auto desc = passDesc.colorAttachments[i];
|
|
|
|
|
|
+static inline void setAttachment(const Graphics::RenderTarget &rt, MTLRenderPassAttachmentDescriptor *desc)
|
|
|
|
+{
|
|
|
|
+ bool isvolume = rt.texture->getTextureType() == TEXTURE_VOLUME;
|
|
|
|
|
|
- desc.texture = (__bridge id<MTLTexture>)(void*)tex->getRenderTargetHandle();
|
|
|
|
- desc.level = rt.mipmap;
|
|
|
|
|
|
+ desc.texture = getMTLRenderTarget(rt.texture);
|
|
|
|
+ desc.level = rt.mipmap;
|
|
|
|
+ desc.slice = isvolume ? 0 : rt.slice;
|
|
|
|
+ desc.depthPlane = isvolume ? rt.slice : 0;
|
|
|
|
|
|
- if (tex->getTextureType() == TEXTURE_VOLUME)
|
|
|
|
- {
|
|
|
|
- desc.slice = 0;
|
|
|
|
- desc.depthPlane = rt.slice;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- desc.slice = rt.slice;
|
|
|
|
- desc.depthPlane = 0;
|
|
|
|
- }
|
|
|
|
|
|
+ // Default to load until clear or discard is called.
|
|
|
|
+ desc.loadAction = MTLLoadActionLoad;
|
|
|
|
+ desc.storeAction = MTLStoreActionStore;
|
|
|
|
|
|
- // Default to load until clear or discard is called.
|
|
|
|
- desc.loadAction = MTLLoadActionLoad;
|
|
|
|
- desc.storeAction = MTLStoreActionStore;
|
|
|
|
|
|
+ desc.resolveTexture = nil;
|
|
|
|
|
|
- desc.resolveTexture = nil;
|
|
|
|
|
|
+ if (rt.texture->getMSAA() > 1)
|
|
|
|
+ {
|
|
|
|
+ // TODO
|
|
|
|
+ desc.resolveTexture = getMTLTexture(rt.texture);
|
|
|
|
|
|
- if (tex->getMSAA() > 1)
|
|
|
|
- {
|
|
|
|
- // TODO
|
|
|
|
- desc.resolveTexture = (__bridge id<MTLTexture>)(void*)tex->getHandle();
|
|
|
|
|
|
+ // TODO: This StoreAction is only supported sometimes.
|
|
|
|
+ desc.storeAction = MTLStoreActionStoreAndMultisampleResolve;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
- // TODO: This StoreAction is only supported sometimes.
|
|
|
|
- desc.storeAction = MTLStoreActionStoreAndMultisampleResolve;
|
|
|
|
- }
|
|
|
|
|
|
+void Graphics::setRenderTargetsInternal(const RenderTargets &rts, int w, int h, int /*pixelw*/, int /*pixelh*/, bool /*hasSRGBtexture*/)
|
|
|
|
+{ @autoreleasepool {
|
|
|
|
+ endPass();
|
|
|
|
|
|
|
|
+ // Set up render pass descriptor for the next useRenderEncoder call.
|
|
|
|
+ // The backbuffer will be set up in useRenderEncoder rather than here.
|
|
|
|
+ for (size_t i = 0; i < rts.colors.size(); i++)
|
|
|
|
+ {
|
|
|
|
+ auto desc = passDesc.colorAttachments[i];
|
|
|
|
+ setAttachment(rts.colors[i], desc);
|
|
passDesc.colorAttachments[i] = desc;
|
|
passDesc.colorAttachments[i] = desc;
|
|
}
|
|
}
|
|
|
|
|
|
for (size_t i = rts.colors.size(); i < MAX_COLOR_RENDER_TARGETS; i++)
|
|
for (size_t i = rts.colors.size(); i < MAX_COLOR_RENDER_TARGETS; i++)
|
|
passDesc.colorAttachments[i] = nil;
|
|
passDesc.colorAttachments[i] = nil;
|
|
|
|
|
|
- // TODO: depth/stencil attachments
|
|
|
|
- // TODO: projection matrix
|
|
|
|
- // TODO: backbuffer
|
|
|
|
|
|
+ passDesc.depthAttachment = nil;
|
|
|
|
+ passDesc.stencilAttachment = nil;
|
|
|
|
+
|
|
|
|
+ if (rts.depthStencil.texture)
|
|
|
|
+ {
|
|
|
|
+ if (isPixelFormatDepth(rts.depthStencil.texture->getPixelFormat()))
|
|
|
|
+ setAttachment(rts.depthStencil, passDesc.depthAttachment);
|
|
|
|
+
|
|
|
|
+ if (isPixelFormatStencil(rts.depthStencil.texture->getPixelFormat()))
|
|
|
|
+ setAttachment(rts.depthStencil, passDesc.stencilAttachment);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ projectionMatrix = Matrix4::ortho(0.0, (float) w, (float) h, 0.0, -10.0f, 10.0f);
|
|
dirtyRenderState = STATEBIT_ALL;
|
|
dirtyRenderState = STATEBIT_ALL;
|
|
}}
|
|
}}
|
|
|
|
|
|
@@ -1093,6 +1101,9 @@ void Graphics::present(void *screenshotCallbackData)
|
|
if (window != nullptr)
|
|
if (window != nullptr)
|
|
window->swapBuffers();
|
|
window->swapBuffers();
|
|
|
|
|
|
|
|
+ // This is set to NO when there are pending screen captures.
|
|
|
|
+ metalLayer.framebufferOnly = YES;
|
|
|
|
+
|
|
activeDrawable = nil;
|
|
activeDrawable = nil;
|
|
|
|
|
|
// Reset the per-frame stat counts.
|
|
// Reset the per-frame stat counts.
|