203 lines
5.8 KiB
Plaintext
Raw Normal View History

2024-11-01 16:55:46 +08:00
#include "RenderAPI.h"
#include "PlatformBase.h"
// Metal implementation of RenderAPI.
#if SUPPORT_METAL
#include "Unity/IUnityGraphicsMetal.h"
#import <Metal/Metal.h>
2024-11-22 12:09:31 +08:00
#import <Foundation/Foundation.h>
#import <MetalFX/MTLFXSpatialScaler.h>
2024-11-01 16:55:46 +08:00
class RenderAPI_Metal : public RenderAPI
{
public:
RenderAPI_Metal();
virtual ~RenderAPI_Metal() { }
2024-11-22 12:09:31 +08:00
virtual void processDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces);
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
virtual bool getUsesReverseZ() { return true; }
2024-11-01 16:55:46 +08:00
2024-11-22 12:09:31 +08:00
virtual void initSupportFeature();
2024-11-01 16:55:46 +08:00
2024-12-18 17:53:48 +08:00
virtual void spatialUpScale(void*data) override;
virtual void enableVRS(void* data) override;
virtual void disableVRS() override;
2024-11-01 16:55:46 +08:00
private:
2024-11-22 12:09:31 +08:00
id <MTLFXSpatialScaler> mfx_spatial_scaler;
2024-12-18 14:27:45 +08:00
id <MTLCommandQueue> commandQueue;
2024-12-20 13:38:57 +08:00
id <MTLTexture> outTexture;
2024-11-22 12:09:31 +08:00
IUnityGraphicsMetal* metal_graphics;
2024-11-01 16:55:46 +08:00
};
RenderAPI* CreateRenderAPI_Metal()
{
return new RenderAPI_Metal();
}
RenderAPI_Metal::RenderAPI_Metal()
{
}
2024-11-22 12:09:31 +08:00
void RenderAPI_Metal::processDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces)
2024-11-01 16:55:46 +08:00
{
if (type == kUnityGfxDeviceEventInitialize)
{
2024-11-22 12:09:31 +08:00
metal_graphics = interfaces->Get<IUnityGraphicsMetal>();
2024-12-18 17:53:48 +08:00
initSupportFeature();
2024-11-01 16:55:46 +08:00
}
else if (type == kUnityGfxDeviceEventShutdown)
{
//@TODO: release resources
}
}
2024-11-22 12:09:31 +08:00
void RenderAPI_Metal::initSupportFeature()
2024-11-01 16:55:46 +08:00
{
2024-12-18 14:20:41 +08:00
if (@available(iOS 16, macOS 13, *))
2024-11-22 12:09:31 +08:00
{
support_features[GraphicsFeature::METAL_FX_SPATIAL_SR] = true;
support_features[GraphicsFeature::METAL_FX_TEMPORAL_SR] = true;
2024-12-18 17:53:48 +08:00
id<MTLDevice> device = metal_graphics->MetalDevice();
if(device)
{
support_features[GraphicsFeature::METAL_VRR] = [device supportsRasterizationRateMapWithLayerCount:1];
}
2024-11-22 12:09:31 +08:00
}
2024-11-01 16:55:46 +08:00
}
2024-12-17 20:50:36 +08:00
void RenderAPI_Metal::spatialUpScale(void* data)
2024-11-01 16:55:46 +08:00
{
2024-12-18 14:20:41 +08:00
if (@available(iOS 16, macOS 13, *))
2024-11-22 12:09:31 +08:00
{
2024-12-17 20:50:36 +08:00
struct DataPack
{
void* src;
void* dst;
2024-12-18 14:20:41 +08:00
bool qulityChange;
2024-12-17 20:50:36 +08:00
};
DataPack* data_pack = static_cast<DataPack*>(data);
id<MTLTexture> srctex = (__bridge id<MTLTexture>)data_pack->src;
id<MTLTexture> dsttex = (__bridge id<MTLTexture>)data_pack->dst;
2024-11-22 12:09:31 +08:00
2024-12-18 17:53:48 +08:00
id<MTLDevice> device = metal_graphics->MetalDevice();
2024-11-22 12:09:31 +08:00
id<MTLCommandBuffer> cmd = (id<MTLCommandBuffer>)metal_graphics->CurrentCommandBuffer();
2024-12-20 13:38:57 +08:00
metal_graphics->EndCurrentCommandEncoder();
2024-11-22 12:09:31 +08:00
cmd.label = @"Upscale Command Buffer";
2024-12-20 13:38:57 +08:00
if (mfx_spatial_scaler == nil )
2024-11-22 12:09:31 +08:00
{
MTLFXSpatialScalerDescriptor* desc = [[MTLFXSpatialScalerDescriptor alloc]init];
desc.inputWidth = [srctex width];
desc.inputHeight = [srctex height];
desc.outputWidth = [dsttex width];
desc.outputHeight = [dsttex height];
desc.colorTextureFormat = [srctex pixelFormat];
desc.outputTextureFormat = [dsttex pixelFormat];
desc.colorProcessingMode = MTLFXSpatialScalerColorProcessingModeLinear;
2024-12-18 17:53:48 +08:00
mfx_spatial_scaler = [desc newSpatialScalerWithDevice:device];
commandQueue = [device newCommandQueue];
2024-12-20 13:38:57 +08:00
MTLTextureDescriptor *texdesc = [[MTLTextureDescriptor alloc] init];
texdesc.width = (int)desc.outputWidth;
texdesc.height = (int)desc.outputHeight;
texdesc.storageMode = MTLStorageModePrivate;
texdesc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;
texdesc.pixelFormat = desc.outputTextureFormat;
outTexture = [device newTextureWithDescriptor:texdesc];
2024-11-22 12:09:31 +08:00
}
2024-12-18 14:27:45 +08:00
if (mfx_spatial_scaler == nil || commandQueue == nil)
{
return;
}
2024-12-20 13:38:57 +08:00
if(!(srctex && dsttex))
2024-12-18 14:20:41 +08:00
{
2024-12-20 13:38:57 +08:00
return;
2024-12-18 14:20:41 +08:00
}
2024-12-20 13:38:57 +08:00
mfx_spatial_scaler.colorTexture = srctex;
mfx_spatial_scaler.outputTexture = outTexture;
mfx_spatial_scaler.inputContentWidth = [srctex width];
mfx_spatial_scaler.inputContentHeight = [srctex height];
// if(!cmd)
// {
// id <MTLCommandBuffer> upscaleCommandBuffer = [commandQueue commandBuffer];
// upscaleCommandBuffer.label = @"Upscale Command Buffer";
// [mfx_spatial_scaler encodeToCommandBuffer:upscaleCommandBuffer];
// [upscaleCommandBuffer commit];
// id <MTLCommandBuffer> textureCommandBuffer = [commandQueue commandBuffer];
// id <MTLBlitCommandEncoder> _mfxSpatialEncoder =[textureCommandBuffer blitCommandEncoder];
// [_mfxSpatialEncoder copyFromTexture: outTexture toTexture: dsttex];
// [_mfxSpatialEncoder endEncoding];
// [textureCommandBuffer commit];
// }
2024-12-18 14:20:41 +08:00
// else
{
2024-12-20 13:38:57 +08:00
[mfx_spatial_scaler encodeToCommandBuffer:cmd];
2024-12-18 14:20:41 +08:00
// [cmd commit];
2024-12-20 13:38:57 +08:00
// id <MTLCommandBuffer> textureCommandBuffer = [commandQueue commandBuffer];
id <MTLBlitCommandEncoder> _mfxSpatialEncoder =[textureCommandBuffer blitCommandEncoder];
[_mfxSpatialEncoder copyFromTexture: outTexture toTexture: dsttex];
[_mfxSpatialEncoder endEncoding];
// [textureCommandBuffer commit];
2024-12-18 14:20:41 +08:00
}
2024-11-22 12:09:31 +08:00
}
2024-11-01 16:55:46 +08:00
}
2024-12-18 17:53:48 +08:00
void RenderAPI_Metal::enableVRS(void* data)
{
struct DataPack
{
float width;
float height;
float ratex;
float ratey;
bool cfgChange;
};
id<MTLDevice> device = metal_graphics->MetalDevice();
DataPack* data_pack = static_cast<DataPack*>(data);
MTLRasterizationRateMapDescriptor *descriptor = [[MTLRasterizationRateMapDescriptor alloc] init];
descriptor.label = @"raster rate map";
descriptor.screenSize = MTLSizeMake(data_pack->width, data_pack->height, 1);
MTLSize zone_counts = MTLSizeMake(8, 4, 1);
MTLRasterizationRateLayerDescriptor *layer_descriptor = [[MTLRasterizationRateLayerDescriptor alloc] initWithSampleCount:zone_counts];
for (int row = 0; row < zone_counts.height; row++)
{
layer_descriptor.verticalSampleStorage[row] = data_pack->ratey;
}
for (int column = 0; column < zone_counts.width; column++)
{
layer_descriptor.horizontalSampleStorage[column] = data_pack->ratex;
}
[descriptor setLayer:layer_descriptor atIndex:0];
id<MTLRasterizationRateMap> rate_map = [device newRasterizationRateMapWithDescriptor: descriptor];
MTLRenderPassDescriptor* current_pass_descriptor= metal_graphics->CurrentRenderPassDescriptor();
current_pass_descriptor.rasterizationRateMap = rate_map;
}
2024-11-01 16:55:46 +08:00
2024-12-18 17:53:48 +08:00
void RenderAPI_Metal::disableVRS()
{
}
2024-11-01 16:55:46 +08:00
#endif // #if SUPPORT_METAL