Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

188 lines
6.5 KiB
Plaintext

//
// Copyright Contributors to the MaterialX Project
// SPDX-License-Identifier: Apache-2.0
//
#include <MaterialXRenderMsl/MetalFramebuffer.h>
#include <MaterialXRenderMsl/MslPipelineStateObject.h>
#include <MaterialXRenderMsl/MslRenderer.h>
#include <MaterialXRenderMsl/MetalTextureHandler.h>
MATERIALX_NAMESPACE_BEGIN
//
// MetalFramebuffer methods
//
MetalFramebufferPtr MetalFramebuffer::create(id<MTLDevice> device,
unsigned int width, unsigned int height,
unsigned channelCount,
Image::BaseType baseType,
id<MTLTexture> colorTexture,
bool encodeSrgb,
MTLPixelFormat pixelFormat)
{
return MetalFramebufferPtr(new MetalFramebuffer(device,
width, height,
channelCount,
baseType,
colorTexture,
encodeSrgb,
pixelFormat));
}
MetalFramebuffer::MetalFramebuffer(id<MTLDevice> device,
unsigned int width, unsigned int height,
unsigned int channelCount,
Image::BaseType baseType,
id<MTLTexture> colorTexture,
bool encodeSrgb,
MTLPixelFormat pixelFormat) :
_width(0),
_height(0),
_channelCount(channelCount),
_baseType(baseType),
_encodeSrgb(encodeSrgb),
_device(device),
_colorTexture(colorTexture),
_depthTexture(0)
{
StringVec errors;
const string errorType("Metal target creation failure.");
resize(width, height, true, pixelFormat, colorTexture);
}
MetalFramebuffer::~MetalFramebuffer()
{
[_colorTexture release];
[_depthTexture release];
}
void MetalFramebuffer::resize(unsigned int width, unsigned int height, bool forceRecreate,
MTLPixelFormat pixelFormat,
id<MTLTexture> extColorTexture)
{
if (width * height <= 0)
{
return;
}
if (width != _width || _height != height || forceRecreate)
{
// Convert texture format to Metal
MTLDataType dataType;
if (pixelFormat == MTLPixelFormatInvalid)
MetalTextureHandler::mapTextureFormatToMetal(_baseType, _channelCount, _encodeSrgb, dataType, pixelFormat);
MTLTextureDescriptor* texDescriptor = [MTLTextureDescriptor
texture2DDescriptorWithPixelFormat:pixelFormat
width:width
height:height
mipmapped:NO];
[texDescriptor setStorageMode:MTLStorageModePrivate];
[texDescriptor setUsage:MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite];
if (extColorTexture == nil)
{
_colorTexture = [_device newTextureWithDescriptor:texDescriptor];
_colorTextureOwned = true;
}
else
{
_colorTexture = extColorTexture;
_colorTextureOwned = false;
}
texDescriptor.pixelFormat = MTLPixelFormatDepth32Float;
[texDescriptor setUsage:MTLTextureUsageRenderTarget];
_depthTexture = [_device newTextureWithDescriptor:texDescriptor];
_width = width;
_height = height;
}
}
void MetalFramebuffer::bind(MTLRenderPassDescriptor* renderpassDesc)
{
[renderpassDesc.colorAttachments[0] setTexture:getColorTexture()];
[renderpassDesc.colorAttachments[0] setLoadAction:MTLLoadActionClear];
[renderpassDesc.colorAttachments[0] setStoreAction:MTLStoreActionStore];
[renderpassDesc.depthAttachment setTexture:getDepthTexture()];
[renderpassDesc.depthAttachment setClearDepth:1.0];
[renderpassDesc.depthAttachment setLoadAction:MTLLoadActionClear];
[renderpassDesc.depthAttachment setStoreAction:MTLStoreActionStore];
[renderpassDesc setStencilAttachment:nil];
[renderpassDesc setRenderTargetWidth:_width];
[renderpassDesc setRenderTargetHeight:_height];
}
void MetalFramebuffer::unbind()
{
}
ImagePtr MetalFramebuffer::getColorImage(id<MTLCommandQueue> cmdQueue, ImagePtr image)
{
if (!image)
{
image = Image::create(_width, _height, _channelCount, _baseType);
image->createResourceBuffer();
}
if (cmdQueue == nil)
{
return image;
}
size_t bytesPerRow = _width * _channelCount * MetalTextureHandler::getTextureBaseTypeSize(_baseType);
size_t bytesPerImage = _height * bytesPerRow;
id<MTLBuffer> buffer = [_device newBufferWithLength:bytesPerImage options:MTLResourceStorageModeShared];
id<MTLCommandBuffer> cmdBuffer = [cmdQueue commandBuffer];
id<MTLBlitCommandEncoder> blitCmdEncoder = [cmdBuffer blitCommandEncoder];
[blitCmdEncoder copyFromTexture:_colorTexture
sourceSlice:0
sourceLevel:0
sourceOrigin:MTLOriginMake(0, 0, 0)
sourceSize:MTLSizeMake(_width, _height, 1)
toBuffer:buffer
destinationOffset:0
destinationBytesPerRow:bytesPerRow
destinationBytesPerImage:bytesPerImage
options:MTLBlitOptionNone];
[blitCmdEncoder endEncoding];
[cmdBuffer commit];
[cmdBuffer waitUntilCompleted];
std::vector<unsigned char> imageData(bytesPerImage);
memcpy(imageData.data(), [buffer contents], bytesPerImage);
if ([_colorTexture pixelFormat] == MTLPixelFormatBGRA8Unorm)
{
for (unsigned int j = 0; j < _height; ++j)
{
unsigned int rawStart = j * (_width * _channelCount);
for (unsigned int i = 0; i < _width; ++i)
{
unsigned int offset = rawStart + _channelCount * i;
unsigned char tmp = imageData[offset + 0];
imageData[offset + 0] = imageData[offset + 2];
imageData[offset + 2] = tmp;
}
}
}
memcpy(image->getResourceBuffer(), imageData.data(), bytesPerImage);
[buffer release];
return image;
}
MATERIALX_NAMESPACE_END