202 lines
5.8 KiB
Plaintext
202 lines
5.8 KiB
Plaintext
|
|
#include "RenderAPI.h"
|
|
#include "PlatformBase.h"
|
|
|
|
|
|
// Metal implementation of RenderAPI.
|
|
|
|
|
|
#if SUPPORT_METAL
|
|
|
|
#include "Unity/IUnityGraphicsMetal.h"
|
|
#import <Metal/Metal.h>
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import <MetalFX/MTLFXSpatialScaler.h>
|
|
|
|
|
|
class RenderAPI_Metal : public RenderAPI
|
|
{
|
|
public:
|
|
RenderAPI_Metal();
|
|
virtual ~RenderAPI_Metal() { }
|
|
|
|
virtual void processDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces);
|
|
|
|
virtual bool getUsesReverseZ() { return true; }
|
|
|
|
virtual void initSupportFeature();
|
|
|
|
virtual void spatialUpScale(void*data) override;
|
|
|
|
virtual void enableVRS(void* data) override;
|
|
virtual void disableVRS() override;
|
|
|
|
private:
|
|
id <MTLFXSpatialScaler> mfx_spatial_scaler;
|
|
id <MTLCommandQueue> commandQueue;
|
|
id <MTLTexture> outTexture;
|
|
IUnityGraphicsMetal* metal_graphics;
|
|
};
|
|
|
|
|
|
RenderAPI* CreateRenderAPI_Metal()
|
|
{
|
|
return new RenderAPI_Metal();
|
|
}
|
|
|
|
|
|
RenderAPI_Metal::RenderAPI_Metal()
|
|
{
|
|
}
|
|
|
|
void RenderAPI_Metal::processDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces)
|
|
{
|
|
if (type == kUnityGfxDeviceEventInitialize)
|
|
{
|
|
metal_graphics = interfaces->Get<IUnityGraphicsMetal>();
|
|
initSupportFeature();
|
|
}
|
|
else if (type == kUnityGfxDeviceEventShutdown)
|
|
{
|
|
//@TODO: release resources
|
|
}
|
|
}
|
|
void RenderAPI_Metal::initSupportFeature()
|
|
{
|
|
if (@available(iOS 16, macOS 13, *))
|
|
{
|
|
support_features[GraphicsFeature::METAL_FX_SPATIAL_SR] = true;
|
|
support_features[GraphicsFeature::METAL_FX_TEMPORAL_SR] = true;
|
|
id<MTLDevice> device = metal_graphics->MetalDevice();
|
|
if(device)
|
|
{
|
|
support_features[GraphicsFeature::METAL_VRR] = [device supportsRasterizationRateMapWithLayerCount:1];
|
|
}
|
|
}
|
|
}
|
|
|
|
void RenderAPI_Metal::spatialUpScale(void* data)
|
|
{
|
|
// if (@available(iOS 16, macOS 13, *))
|
|
{
|
|
struct DataPack
|
|
{
|
|
void* src;
|
|
void* dst;
|
|
bool qulityChange;
|
|
};
|
|
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;
|
|
|
|
id<MTLDevice> device = metal_graphics->MetalDevice();
|
|
id<MTLCommandBuffer> cmd = (id<MTLCommandBuffer>)metal_graphics->CurrentCommandBuffer();
|
|
// metal_graphics->EndCurrentCommandEncoder();
|
|
cmd.label = @"Upscale Command Buffer";
|
|
if (mfx_spatial_scaler == nil )
|
|
{
|
|
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;
|
|
|
|
mfx_spatial_scaler = [desc newSpatialScalerWithDevice:device];
|
|
commandQueue = [device newCommandQueue];
|
|
|
|
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];
|
|
}
|
|
|
|
if (mfx_spatial_scaler == nil || commandQueue == nil)
|
|
{
|
|
return;
|
|
}
|
|
if(!(srctex && dsttex))
|
|
{
|
|
return;
|
|
}
|
|
mfx_spatial_scaler.colorTexture = srctex;
|
|
mfx_spatial_scaler.outputTexture = dsttex;
|
|
|
|
// 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];
|
|
// }
|
|
// else
|
|
{
|
|
// [mfx_spatial_scaler encodeToCommandBuffer:cmd];
|
|
// [cmd commit];
|
|
|
|
// id <MTLCommandBuffer> textureCommandBuffer = [commandQueue commandBuffer];
|
|
// id <MTLBlitCommandEncoder> _mfxSpatialEncoder =[textureCommandBuffer blitCommandEncoder];
|
|
|
|
// [_mfxSpatialEncoder copyFromTexture: outTexture toTexture: dsttex];
|
|
// [_mfxSpatialEncoder endEncoding];
|
|
// [textureCommandBuffer commit];
|
|
}
|
|
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|
|
void RenderAPI_Metal::disableVRS()
|
|
{
|
|
|
|
}
|
|
#endif // #if SUPPORT_METAL
|