mirror of
https://github.com/OpenEmu/PCSX2-Core.git
synced 2025-11-01 11:07:36 +00:00
Update PCSX2.
This commit is contained in:
+166
-72
@@ -71,7 +71,6 @@ GSDeviceMTL::GSDeviceMTL()
|
||||
, m_dev(nil)
|
||||
{
|
||||
m_backref->second = this;
|
||||
m_mipmap = theApp.GetConfigI("mipmap");
|
||||
}
|
||||
|
||||
GSDeviceMTL::~GSDeviceMTL()
|
||||
@@ -120,10 +119,10 @@ GSDeviceMTL::Map GSDeviceMTL::Allocate(BufferPair& buffer, size_t amt)
|
||||
{
|
||||
id<MTLBlitCommandEncoder> enc = GetVertexUploadEncoder();
|
||||
[enc copyFromBuffer:buffer.cpubuffer
|
||||
sourceOffset:buffer.last_upload
|
||||
toBuffer:buffer.gpubuffer
|
||||
sourceOffset:buffer.last_upload
|
||||
toBuffer:buffer.gpubuffer
|
||||
destinationOffset:buffer.last_upload
|
||||
size:base_pos - buffer.last_upload];
|
||||
size:base_pos - buffer.last_upload];
|
||||
}
|
||||
buffer.last_upload = 0;
|
||||
}
|
||||
@@ -160,10 +159,10 @@ void GSDeviceMTL::Sync(BufferPair& buffer)
|
||||
|
||||
id<MTLBlitCommandEncoder> enc = GetVertexUploadEncoder();
|
||||
[enc copyFromBuffer:buffer.cpubuffer
|
||||
sourceOffset:buffer.last_upload
|
||||
toBuffer:buffer.gpubuffer
|
||||
sourceOffset:buffer.last_upload
|
||||
toBuffer:buffer.gpubuffer
|
||||
destinationOffset:buffer.last_upload
|
||||
size:buffer.usage.Pos() - buffer.last_upload];
|
||||
size:buffer.usage.Pos() - buffer.last_upload];
|
||||
[enc updateFence:m_draw_sync_fence];
|
||||
buffer.last_upload = buffer.usage.Pos();
|
||||
}
|
||||
@@ -257,6 +256,40 @@ void GSDeviceMTL::FlushEncoders()
|
||||
dev->m_last_finished_draw.store(newval, std::memory_order_release);
|
||||
}
|
||||
}];
|
||||
if (m_last_spin_cmdbuf)
|
||||
{
|
||||
double seconds_to_spin = m_spin_timer.GetTimeSeconds();
|
||||
[m_current_render_cmdbuf addCompletedHandler:[spin = std::move(m_last_spin_cmdbuf), backref = m_backref, seconds_to_spin](id<MTLCommandBuffer> render){
|
||||
if (@available(macOS 10.15, iOS 10.3, *))
|
||||
{
|
||||
CFTimeInterval start = [spin GPUStartTime];
|
||||
CFTimeInterval end = [spin GPUEndTime];
|
||||
CFTimeInterval rstart = [render GPUStartTime];
|
||||
[[maybe_unused]] CFTimeInterval spin_time = end - start;
|
||||
[[maybe_unused]] CFTimeInterval total_time = rstart - start;
|
||||
// Console.WriteLn("Spin Result: duration: %.2fms, time to fill: %.2fms, ratio: %.2f, target: %.2fms", spin_time * 1000, total_time * 1000, spin_time / total_time, seconds_to_spin * 1000);
|
||||
std::lock_guard<std::mutex> lock(backref->first);
|
||||
if (GSDeviceMTL* dev = backref->second)
|
||||
{
|
||||
if (!start || !end)
|
||||
{
|
||||
Console.Warning("Spin never ended???");
|
||||
}
|
||||
else if (spin_time < seconds_to_spin - 0.001)
|
||||
{
|
||||
dev->m_spin_cycles += (dev->m_spin_cycles >> 4);
|
||||
// Console.WriteLn("Spin finished early, increasing cycles to %d", dev->m_spin_cycles);
|
||||
}
|
||||
else if (spin_time > seconds_to_spin)
|
||||
{
|
||||
dev->m_spin_cycles -= (dev->m_spin_cycles >> 4);
|
||||
// Console.WriteLn("Spin finished late, reducing cycles to %d", dev->m_spin_cycles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
m_last_spin_cmdbuf = nil;
|
||||
}
|
||||
[m_current_render_cmdbuf commit];
|
||||
m_current_render_cmdbuf = nil;
|
||||
m_current_draw++;
|
||||
@@ -274,14 +307,14 @@ void GSDeviceMTL::EndRenderPass()
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceMTL::BeginRenderPass(NSString* name, GSTexture* color, MTLLoadAction color_load, GSTexture* depth, MTLLoadAction depth_load, GSTexture* stencil, MTLLoadAction stencil_load)
|
||||
void GSDeviceMTL::BeginRenderPass(NSString* name, GSTexture* color, MTLLoadAction color_load, GSTexture* depth, MTLLoadAction depth_load, GSTexture* stencil, MTLLoadAction stencil_load, GSVector2i size)
|
||||
{
|
||||
GSTextureMTL* mc = static_cast<GSTextureMTL*>(color);
|
||||
GSTextureMTL* md = static_cast<GSTextureMTL*>(depth);
|
||||
GSTextureMTL* ms = static_cast<GSTextureMTL*>(stencil);
|
||||
bool needs_new = color != m_current_render.color_target
|
||||
|| depth != m_current_render.depth_target
|
||||
|| stencil != m_current_render.stencil_target;
|
||||
|| depth != m_current_render.depth_target
|
||||
|| stencil != m_current_render.stencil_target;
|
||||
GSVector4 color_clear;
|
||||
float depth_clear = 0;
|
||||
int stencil_clear = 0;
|
||||
@@ -297,6 +330,12 @@ void GSDeviceMTL::BeginRenderPass(NSString* name, GSTexture* color, MTLLoadActio
|
||||
needs_new |= mc && color_load == MTLLoadActionClear;
|
||||
needs_new |= md && depth_load == MTLLoadActionClear;
|
||||
needs_new |= ms && stencil_load == MTLLoadActionClear;
|
||||
if (m_current_render.size != GSVector2i(0, 0))
|
||||
{
|
||||
needs_new |= size == GSVector2i(0, 0);
|
||||
needs_new |= size.x > m_current_render.size.x;
|
||||
needs_new |= size.y > m_current_render.size.y;
|
||||
}
|
||||
|
||||
if (!needs_new)
|
||||
{
|
||||
@@ -345,16 +384,28 @@ void GSDeviceMTL::BeginRenderPass(NSString* name, GSTexture* color, MTLLoadActio
|
||||
desc.stencilAttachment.loadAction = stencil_load;
|
||||
}
|
||||
|
||||
if (@available(macOS 10.15, iOS 11, *))
|
||||
{
|
||||
desc.renderTargetWidth = size.x;
|
||||
desc.renderTargetHeight = size.y;
|
||||
}
|
||||
|
||||
EndRenderPass();
|
||||
m_current_render.encoder = MRCRetain([GetRenderCmdBuf() renderCommandEncoderWithDescriptor:desc]);
|
||||
m_current_render.name = (__bridge void*)name;
|
||||
[m_current_render.encoder setLabel:name];
|
||||
if (!m_dev.features.unified_memory)
|
||||
[m_current_render.encoder waitForFence:m_draw_sync_fence
|
||||
beforeStages:MTLRenderStageVertex];
|
||||
beforeStages:MTLRenderStageVertex];
|
||||
m_current_render.color_target = color;
|
||||
m_current_render.depth_target = depth;
|
||||
m_current_render.stencil_target = stencil;
|
||||
m_current_render.size = size;
|
||||
if (size != GSVector2i(0, 0))
|
||||
{
|
||||
GSVector2i rtsize = color ? color->GetSize() : depth ? depth->GetSize() : stencil->GetSize();
|
||||
[m_current_render.encoder setViewport: (MTLViewport){ .originX = 0, .originY = 0, .width = (double)rtsize.x, .height = (double)rtsize.y, .znear = 0, .zfar = 1 }];
|
||||
}
|
||||
pxAssertRel(m_current_render.encoder, "Failed to create render encoder!");
|
||||
}
|
||||
|
||||
@@ -384,9 +435,9 @@ GSTexture* GSDeviceMTL::CreateSurface(GSTexture::Type type, int width, int heigh
|
||||
|
||||
MTLTextureDescriptor* desc = [MTLTextureDescriptor
|
||||
texture2DDescriptorWithPixelFormat:fmt
|
||||
width:std::max(1, std::min(width, m_dev.features.max_texsize))
|
||||
height:std::max(1, std::min(height, m_dev.features.max_texsize))
|
||||
mipmapped:levels > 1];
|
||||
width:std::max(1, std::min(width, m_dev.features.max_texsize))
|
||||
height:std::max(1, std::min(height, m_dev.features.max_texsize))
|
||||
mipmapped:levels > 1];
|
||||
|
||||
if (levels > 1)
|
||||
[desc setMipmapLevelCount:levels];
|
||||
@@ -400,6 +451,13 @@ GSTexture* GSDeviceMTL::CreateSurface(GSTexture::Type type, int width, int heigh
|
||||
case GSTexture::Type::Offscreen:
|
||||
[desc setUsage:MTLTextureUsageRenderTarget];
|
||||
break;
|
||||
case GSTexture::Type::RenderTarget:
|
||||
case GSTexture::Type::SparseRenderTarget:
|
||||
if (m_dev.features.slow_color_compression)
|
||||
[desc setUsage:MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget | MTLTextureUsagePixelFormatView]; // Force color compression off by including PixelFormatView
|
||||
else
|
||||
[desc setUsage:MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget];
|
||||
break;
|
||||
default:
|
||||
[desc setUsage:MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget];
|
||||
}
|
||||
@@ -507,8 +565,8 @@ void GSDeviceMTL::DoShadeBoost(GSTexture* sTex, GSTexture* dTex)
|
||||
{
|
||||
BeginRenderPass(@"ShadeBoost", dTex, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare);
|
||||
[m_current_render.encoder setFragmentBytes:&m_shadeboost_constants
|
||||
length:sizeof(m_shadeboost_constants)
|
||||
atIndex:GSMTLBufferIndexUniforms];
|
||||
length:sizeof(m_shadeboost_constants)
|
||||
atIndex:GSMTLBufferIndexUniforms];
|
||||
RenderCopy(sTex, m_shadeboost_pipeline, GSVector4i(0, 0, dTex->GetSize().x, dTex->GetSize().y));
|
||||
}
|
||||
|
||||
@@ -605,6 +663,16 @@ bool GSDeviceMTL::Create(HostDisplay* display)
|
||||
m_queue = MRCRetain((__bridge id<MTLCommandQueue>)m_display->GetRenderContext());
|
||||
MTLPixelFormat layer_px_fmt = [(__bridge CAMetalLayer*)m_display->GetRenderSurface() pixelFormat];
|
||||
|
||||
if (const char* env = getenv("MTL_SPIN_READBACK"))
|
||||
m_spin_enable = env[0] == '1' || env[0] == 'y' || env[0] == 'Y';
|
||||
else
|
||||
m_spin_enable = false;
|
||||
|
||||
if (const char* env = getenv("MTL_SMALL_RT"))
|
||||
m_enable_small_rt = env[0] == '1' || env[0] == 'y' || env[0] == 'Y';
|
||||
else
|
||||
m_enable_small_rt = false;
|
||||
|
||||
m_features.geometry_shader = false;
|
||||
m_features.image_load_store = m_dev.features.primid;
|
||||
m_features.texture_barrier = true;
|
||||
@@ -784,10 +852,10 @@ bool GSDeviceMTL::Create(HostDisplay* display)
|
||||
pdesc.stencilAttachmentPixelFormat = MTLPixelFormatInvalid;
|
||||
pdesc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||
m_primid_init_pipeline[1][0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm0"), @"PrimID DATM0 Clear");
|
||||
m_primid_init_pipeline[1][1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm0"), @"PrimID DATM1 Clear");
|
||||
m_primid_init_pipeline[1][1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm1"), @"PrimID DATM1 Clear");
|
||||
pdesc.depthAttachmentPixelFormat = MTLPixelFormatInvalid;
|
||||
m_primid_init_pipeline[0][0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm0"), @"PrimID DATM0 Clear");
|
||||
m_primid_init_pipeline[0][1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm0"), @"PrimID DATM1 Clear");
|
||||
m_primid_init_pipeline[0][1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm1"), @"PrimID DATM1 Clear");
|
||||
|
||||
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::Color);
|
||||
applyAttribute(pdesc.vertexDescriptor, 0, MTLVertexFormatFloat2, offsetof(ConvertShaderVertex, pos), 0);
|
||||
@@ -928,18 +996,50 @@ bool GSDeviceMTL::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSText
|
||||
[cmdbuf pushDebugGroup:@"DownloadTexture"];
|
||||
id<MTLBlitCommandEncoder> encoder = [cmdbuf blitCommandEncoder];
|
||||
[encoder copyFromTexture:msrc->GetTexture()
|
||||
sourceSlice:0
|
||||
sourceLevel:0
|
||||
sourceOrigin:MTLOriginMake(rect.x, rect.y, 0)
|
||||
sourceSize:MTLSizeMake(rect.width(), rect.height(), 1)
|
||||
toBuffer:m_texture_download_buf
|
||||
destinationOffset:0
|
||||
sourceSlice:0
|
||||
sourceLevel:0
|
||||
sourceOrigin:MTLOriginMake(rect.x, rect.y, 0)
|
||||
sourceSize:MTLSizeMake(rect.width(), rect.height(), 1)
|
||||
toBuffer:m_texture_download_buf
|
||||
destinationOffset:0
|
||||
destinationBytesPerRow:out_map.pitch
|
||||
destinationBytesPerImage:size];
|
||||
if (m_spin_enable)
|
||||
[encoder updateFence:m_draw_sync_fence];
|
||||
[encoder endEncoding];
|
||||
[cmdbuf popDebugGroup];
|
||||
|
||||
FlushEncoders();
|
||||
if (m_spin_enable)
|
||||
{
|
||||
if (@available(macOS 10.15, iOS 10.3, *))
|
||||
{
|
||||
id<MTLCommandBuffer> spin_cmdbuf = [m_queue commandBuffer];
|
||||
id<MTLComputeCommandEncoder> spin_enc = [spin_cmdbuf computeCommandEncoder];
|
||||
[spin_enc waitForFence:m_draw_sync_fence];
|
||||
if (!m_spin_pipeline)
|
||||
m_spin_pipeline = MRCTransfer([m_dev.dev newComputePipelineStateWithFunction:LoadShader(@"waste_time") error:nil]);
|
||||
if (!m_spin_buf)
|
||||
m_spin_buf = MRCTransfer([m_dev.dev newBufferWithLength:4 options:MTLResourceStorageModeShared]);
|
||||
*(u32*)[m_spin_buf contents] = 0;
|
||||
[spin_enc setComputePipelineState:m_spin_pipeline];
|
||||
[spin_enc setBuffer:m_spin_buf offset:0 atIndex:1];
|
||||
if (m_spin_cycles < 1024)
|
||||
m_spin_cycles = 1024;
|
||||
// Console.WriteLn("Metal: Spin %d iters", m_spin_cycles);
|
||||
[spin_enc setBytes:&m_spin_cycles length:4 atIndex:0];
|
||||
[spin_enc dispatchThreads:MTLSizeMake(1, 1, 1) threadsPerThreadgroup:MTLSizeMake(1, 1, 1)];
|
||||
[spin_enc endEncoding];
|
||||
[spin_cmdbuf commit];
|
||||
m_last_spin_cmdbuf = MRCRetain(spin_cmdbuf);
|
||||
// Don't let the CPU go to sleep either!
|
||||
while (![cmdbuf GPUEndTime])
|
||||
ShortSpin();
|
||||
|
||||
m_spin_timer.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
[cmdbuf waitUntilCompleted];
|
||||
|
||||
out_map.bits = static_cast<u8*>([m_texture_download_buf contents]);
|
||||
@@ -970,14 +1070,14 @@ void GSDeviceMTL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
|
||||
id<MTLBlitCommandEncoder> encoder = [cmdbuf blitCommandEncoder];
|
||||
[encoder setLabel:@"CopyRect"];
|
||||
[encoder copyFromTexture:sT->GetTexture()
|
||||
sourceSlice:0
|
||||
sourceLevel:0
|
||||
sourceOrigin:MTLOriginMake(r.x, r.y, 0)
|
||||
sourceSize:MTLSizeMake(r.width(), r.height(), 1)
|
||||
toTexture:dT->GetTexture()
|
||||
destinationSlice:0
|
||||
destinationLevel:0
|
||||
destinationOrigin:MTLOriginMake(0, 0, 0)];
|
||||
sourceSlice:0
|
||||
sourceLevel:0
|
||||
sourceOrigin:MTLOriginMake(r.x, r.y, 0)
|
||||
sourceSize:MTLSizeMake(r.width(), r.height(), 1)
|
||||
toTexture:dT->GetTexture()
|
||||
destinationSlice:0
|
||||
destinationLevel:0
|
||||
destinationOrigin:MTLOriginMake(0, 0, 0)];
|
||||
[encoder endEncoding];
|
||||
}}
|
||||
|
||||
@@ -993,9 +1093,9 @@ void GSDeviceMTL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextu
|
||||
GSVector2i ds = dT->GetSize();
|
||||
|
||||
bool covers_target = static_cast<int>(dRect.x) <= 0
|
||||
&& static_cast<int>(dRect.y) <= 0
|
||||
&& static_cast<int>(dRect.z) >= ds.x
|
||||
&& static_cast<int>(dRect.w) >= ds.y;
|
||||
&& static_cast<int>(dRect.y) <= 0
|
||||
&& static_cast<int>(dRect.z) >= ds.x
|
||||
&& static_cast<int>(dRect.w) >= ds.y;
|
||||
bool dontcare = load_action == LoadAction::DontCare || (load_action == LoadAction::DontCareIfFull && covers_target);
|
||||
MTLLoadAction action = dontcare ? MTLLoadActionDontCare : MTLLoadActionLoad;
|
||||
|
||||
@@ -1042,8 +1142,8 @@ void GSDeviceMTL::DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect
|
||||
[m_current_render.encoder setVertexBytes:vertices length:sizeof(vertices) atIndex:GSMTLBufferIndexVertices];
|
||||
|
||||
[m_current_render.encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip
|
||||
vertexStart:0
|
||||
vertexCount:4];
|
||||
vertexStart:0
|
||||
vertexCount:4];
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
|
||||
}
|
||||
|
||||
@@ -1259,8 +1359,8 @@ static void textureBarrier(id<MTLRenderCommandEncoder> enc)
|
||||
{
|
||||
if (@available(macOS 10.14, *)) {
|
||||
[enc memoryBarrierWithScope:MTLBarrierScopeRenderTargets
|
||||
afterStages:MTLRenderStageFragment
|
||||
beforeStages:MTLRenderStageFragment];
|
||||
afterStages:MTLRenderStageFragment
|
||||
beforeStages:MTLRenderStageFragment];
|
||||
} else {
|
||||
[enc textureBarrier];
|
||||
}
|
||||
@@ -1439,6 +1539,9 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
|
||||
memcpy(allocation.cpu_buffer, config.verts, vertsize);
|
||||
memcpy(static_cast<u8*>(allocation.cpu_buffer) + vertsize, config.indices, idxsize);
|
||||
|
||||
FlushClears(config.tex);
|
||||
FlushClears(config.pal);
|
||||
|
||||
GSTexture* stencil = nullptr;
|
||||
GSTexture* primid_tex = nullptr;
|
||||
GSTexture* rt = config.rt;
|
||||
@@ -1449,6 +1552,7 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
|
||||
break; // No setup
|
||||
case GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking:
|
||||
{
|
||||
FlushClears(config.rt);
|
||||
GSVector2i size = config.rt->GetSize();
|
||||
primid_tex = CreateRenderTarget(size.x, size.y, GSTexture::Format::PrimID);
|
||||
DepthStencilSelector dsel = config.depth;
|
||||
@@ -1493,36 +1597,26 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
}
|
||||
|
||||
FlushClears(config.tex);
|
||||
FlushClears(config.pal);
|
||||
|
||||
// Try to reduce render pass restarts
|
||||
if (!stencil && config.depth.key == DepthStencilSelector::NoDepth().key && (m_current_render.color_target != rt || m_current_render.depth_target != config.ds))
|
||||
config.ds = nullptr;
|
||||
if (!config.ds && m_current_render.color_target == rt && stencil == m_current_render.stencil_target && m_current_render.depth_target != config.tex)
|
||||
config.ds = m_current_render.depth_target;
|
||||
|
||||
BeginRenderPass(@"RenderHW", rt, MTLLoadActionLoad, config.ds, MTLLoadActionLoad, stencil, MTLLoadActionLoad);
|
||||
GSVector2i rtsize = m_enable_small_rt ? GSVector2i(config.scissor.z, config.scissor.w) : GSVector2i(0, 0);
|
||||
BeginRenderPass(@"RenderHW", rt, MTLLoadActionLoad, config.ds, MTLLoadActionLoad, stencil, MTLLoadActionLoad, rtsize);
|
||||
id<MTLRenderCommandEncoder> mtlenc = m_current_render.encoder;
|
||||
FlushDebugEntries(mtlenc);
|
||||
MRESetScissor(config.scissor);
|
||||
MRESetTexture(config.tex, GSMTLTextureIndexTex);
|
||||
MRESetTexture(config.pal, GSMTLTextureIndexPalette);
|
||||
MREInitHWDraw(config, allocation);
|
||||
if (config.require_one_barrier || config.require_full_barrier)
|
||||
MRESetTexture(config.rt, GSMTLTextureIndexRenderTarget);
|
||||
if (primid_tex)
|
||||
MRESetTexture(primid_tex, GSMTLTextureIndexPrimIDs);
|
||||
MRESetSampler(config.sampler);
|
||||
if (config.blend.index && config.blend.is_constant)
|
||||
MRESetBlendColor(config.blend.factor);
|
||||
MRESetHWPipelineState(config.vs, config.ps, config.blend, config.colormask);
|
||||
MRESetDSS(config.depth);
|
||||
|
||||
MRESetCB(config.cb_vs);
|
||||
MRESetCB(config.cb_ps);
|
||||
|
||||
MRESetVertices(allocation.gpu_buffer, allocation.gpu_offset);
|
||||
|
||||
SendHWDraw(config, mtlenc, allocation.gpu_buffer, allocation.gpu_offset + vertsize);
|
||||
|
||||
if (config.alpha_second_pass.enable)
|
||||
@@ -1582,10 +1676,10 @@ void GSDeviceMTL::SendHWDraw(GSHWDrawConfig& config, id<MTLRenderCommandEncoder>
|
||||
count = (*config.drawlist)[n] * config.indices_per_prim;
|
||||
textureBarrier(enc);
|
||||
[enc drawIndexedPrimitives:topology
|
||||
indexCount:count
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off + p * sizeof(*config.indices)];
|
||||
indexCount:count
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off + p * sizeof(*config.indices)];
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
|
||||
}
|
||||
[enc popDebugGroup];
|
||||
@@ -1597,10 +1691,10 @@ void GSDeviceMTL::SendHWDraw(GSHWDrawConfig& config, id<MTLRenderCommandEncoder>
|
||||
{
|
||||
textureBarrier(enc);
|
||||
[enc drawIndexedPrimitives:topology
|
||||
indexCount:config.indices_per_prim
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off + p * sizeof(*config.indices)];
|
||||
indexCount:config.indices_per_prim
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off + p * sizeof(*config.indices)];
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
|
||||
}
|
||||
[enc popDebugGroup];
|
||||
@@ -1610,20 +1704,20 @@ void GSDeviceMTL::SendHWDraw(GSHWDrawConfig& config, id<MTLRenderCommandEncoder>
|
||||
// One barrier needed
|
||||
textureBarrier(enc);
|
||||
[enc drawIndexedPrimitives:topology
|
||||
indexCount:config.nindices
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off];
|
||||
indexCount:config.nindices
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off];
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No barriers needed
|
||||
[enc drawIndexedPrimitives:topology
|
||||
indexCount:config.nindices
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off];
|
||||
indexCount:config.nindices
|
||||
indexType:MTLIndexTypeUInt32
|
||||
indexBuffer:buffer
|
||||
indexBufferOffset:off];
|
||||
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
|
||||
}
|
||||
}
|
||||
@@ -1794,10 +1888,10 @@ void GSDeviceMTL::EndDebugGroup(id<MTLCommandEncoder> enc)
|
||||
//
|
||||
// [enc setVertexBufferOffset:map.gpu_offset + vtx_off + cmd.VtxOffset * sizeof(ImDrawVert) atIndex:0];
|
||||
// [enc drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
// indexCount:cmd.ElemCount
|
||||
// indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
|
||||
// indexBuffer:map.gpu_buffer
|
||||
// indexBufferOffset:map.gpu_offset + idx_off + cmd.IdxOffset * sizeof(ImDrawIdx)];
|
||||
// indexCount:cmd.ElemCount
|
||||
// indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
|
||||
// indexBuffer:map.gpu_buffer
|
||||
// indexBufferOffset:map.gpu_offset + idx_off + cmd.IdxOffset * sizeof(ImDrawIdx)];
|
||||
// }
|
||||
//
|
||||
// vtx_off += vtx_size;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "MetalHostDisplay.h"
|
||||
#include "GS/Renderers/Metal/GSMetalCPPAccessible.h"
|
||||
#include "GS/Renderers/Metal/GSDeviceMTL.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
@@ -43,13 +44,11 @@ HostDisplay* MakeMetalHostDisplay()
|
||||
}
|
||||
|
||||
MetalHostDisplay::MetalHostDisplay()
|
||||
: m_gpu_work_sema(dispatch_semaphore_create(3))
|
||||
{
|
||||
}
|
||||
|
||||
MetalHostDisplay::~MetalHostDisplay()
|
||||
{
|
||||
dispatch_release(m_gpu_work_sema);
|
||||
}
|
||||
|
||||
HostDisplay::AdapterAndModeList GetMetalAdapterAndModeList()
|
||||
@@ -143,7 +142,6 @@ bool MetalHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view
|
||||
AttachSurfaceOnMainThread();
|
||||
});
|
||||
SetVSync(vsync);
|
||||
m_drawable_fetcher.Start(m_layer);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -169,7 +167,6 @@ void MetalHostDisplay::DestroyRenderSurface()
|
||||
{
|
||||
if (!m_layer)
|
||||
return;
|
||||
m_drawable_fetcher.Stop();
|
||||
OnMainThread([this]{ DetachSurfaceOnMainThread(); });
|
||||
m_layer = nullptr;
|
||||
}
|
||||
@@ -216,7 +213,6 @@ void MetalHostDisplay::ResizeRenderWindow(s32 new_window_width, s32 new_window_h
|
||||
@autoreleasepool
|
||||
{
|
||||
[m_layer setDrawableSize:CGSizeMake(new_window_width, new_window_height)];
|
||||
m_drawable_fetcher.GetIfAvailable(); // Throw away the last drawable of the old size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,9 +220,9 @@ std::unique_ptr<HostDisplayTexture> MetalHostDisplay::CreateTexture(u32 width, u
|
||||
{ @autoreleasepool {
|
||||
MTLTextureDescriptor* desc = [MTLTextureDescriptor
|
||||
texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
|
||||
width:width
|
||||
height:height
|
||||
mipmapped:false];
|
||||
width:width
|
||||
height:height
|
||||
mipmapped:false];
|
||||
[desc setUsage:MTLTextureUsageShaderRead];
|
||||
[desc setStorageMode:MTLStorageModePrivate];
|
||||
MRCOwned<id<MTLTexture>> tex = MRCTransfer([m_dev.dev newTextureWithDescriptor:desc]);
|
||||
@@ -246,11 +242,11 @@ void MetalHostDisplay::UpdateTexture(id<MTLTexture> texture, u32 x, u32 y, u32 w
|
||||
MRCOwned<id<MTLBuffer>> buf = MRCTransfer([m_dev.dev newBufferWithLength:bytes options:MTLResourceStorageModeShared | MTLResourceCPUCacheModeWriteCombined]);
|
||||
memcpy([buf contents], data, bytes);
|
||||
[enc copyFromBuffer:buf
|
||||
sourceOffset:0
|
||||
sourceOffset:0
|
||||
sourceBytesPerRow:data_stride
|
||||
sourceBytesPerImage:bytes
|
||||
sourceSize:MTLSizeMake(width, height, 1)
|
||||
toTexture:texture
|
||||
sourceSize:MTLSizeMake(width, height, 1)
|
||||
toTexture:texture
|
||||
destinationSlice:0
|
||||
destinationLevel:0
|
||||
destinationOrigin:MTLOriginMake(0, 0, 0)];
|
||||
@@ -270,24 +266,24 @@ bool MetalHostDisplay::BeginPresent(bool frame_skip)
|
||||
GSDeviceMTL* dev = static_cast<GSDeviceMTL*>(g_gs_device.get());
|
||||
if (dev && m_capture_start_frame && dev->FrameNo() == m_capture_start_frame)
|
||||
s_capture_next = true;
|
||||
static bool f8 = false;
|
||||
bool option = CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_Option) || CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_RightOption);
|
||||
bool newf8 = CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, kVK_F8) && option;
|
||||
if (newf8 && !f8)
|
||||
s_capture_next = true;
|
||||
f8 = newf8;
|
||||
if (frame_skip || m_window_info.type == WindowInfo::Type::Surfaceless || !g_gs_device)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
id<MTLCommandBuffer> buf = dev->GetRenderCmdBuf();
|
||||
// TODO: Use synchronous fetch if vsync is enabled
|
||||
dispatch_semaphore_wait(m_gpu_work_sema, DISPATCH_TIME_FOREVER);
|
||||
dispatch_retain(m_gpu_work_sema);
|
||||
[buf addCompletedHandler:[sema = m_gpu_work_sema](id<MTLCommandBuffer>){ dispatch_semaphore_signal(sema); dispatch_release(sema); }];
|
||||
m_current_drawable = m_drawable_fetcher.GetIfAvailable();
|
||||
m_current_drawable = MRCRetain([m_layer nextDrawable]);
|
||||
dev->EndRenderPass();
|
||||
if (!m_current_drawable)
|
||||
{
|
||||
[buf pushDebugGroup:@"Present Skipped"];
|
||||
[buf popDebugGroup];
|
||||
dev->FlushEncoders();
|
||||
|
||||
return false;
|
||||
}
|
||||
[m_pass_desc colorAttachments][0].texture = [m_current_drawable texture];
|
||||
@@ -301,58 +297,56 @@ void MetalHostDisplay::EndPresent()
|
||||
{ @autoreleasepool {
|
||||
GSDeviceMTL* dev = static_cast<GSDeviceMTL*>(g_gs_device.get());
|
||||
pxAssertDev(dev && dev->m_current_render.encoder && dev->m_current_render_cmdbuf, "BeginPresent cmdbuf was destroyed");
|
||||
|
||||
dev->EndRenderPass();
|
||||
if (m_current_drawable)
|
||||
[dev->GetRenderCmdBuf() presentDrawable:m_current_drawable];
|
||||
[dev->m_current_render_cmdbuf addScheduledHandler:[drawable = std::move(m_current_drawable)](id<MTLCommandBuffer>){
|
||||
[drawable present];
|
||||
}];
|
||||
dev->FlushEncoders();
|
||||
m_current_drawable = nullptr;
|
||||
if (m_capture_start_frame)
|
||||
if (@available(macOS 10.15, iOS 13, *))
|
||||
{
|
||||
if (@available(macOS 10.15, iOS 13, *))
|
||||
static NSString* const path = @"/tmp/PCSX2MTLCapture.gputrace";
|
||||
static u32 frames;
|
||||
if (frames)
|
||||
{
|
||||
static NSString* const path = @"/tmp/PCSX2MTLCapture.gputrace";
|
||||
static u32 frames;
|
||||
if (frames)
|
||||
--frames;
|
||||
if (!frames)
|
||||
{
|
||||
--frames;
|
||||
if (!frames)
|
||||
{
|
||||
[[MTLCaptureManager sharedCaptureManager] stopCapture];
|
||||
Console.WriteLn("Metal Trace Capture to /tmp/PCSX2MTLCapture.gputrace finished");
|
||||
[[NSWorkspace sharedWorkspace] selectFile:path
|
||||
inFileViewerRootedAtPath:@"/tmp/"];
|
||||
}
|
||||
[[MTLCaptureManager sharedCaptureManager] stopCapture];
|
||||
Console.WriteLn("Metal Trace Capture to /tmp/PCSX2MTLCapture.gputrace finished");
|
||||
[[NSWorkspace sharedWorkspace] selectFile:path
|
||||
inFileViewerRootedAtPath:@"/tmp/"];
|
||||
}
|
||||
else if (s_capture_next)
|
||||
}
|
||||
else if (s_capture_next)
|
||||
{
|
||||
s_capture_next = false;
|
||||
MTLCaptureManager* mgr = [MTLCaptureManager sharedCaptureManager];
|
||||
if ([mgr supportsDestination:MTLCaptureDestinationGPUTraceDocument])
|
||||
{
|
||||
s_capture_next = false;
|
||||
MTLCaptureManager* mgr = [MTLCaptureManager sharedCaptureManager];
|
||||
if ([mgr supportsDestination:MTLCaptureDestinationGPUTraceDocument])
|
||||
MTLCaptureDescriptor* desc = [[MTLCaptureDescriptor new] autorelease];
|
||||
[desc setCaptureObject:m_dev.dev];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
|
||||
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
|
||||
[desc setOutputURL:[NSURL fileURLWithPath:path]];
|
||||
[desc setDestination:MTLCaptureDestinationGPUTraceDocument];
|
||||
NSError* err = nullptr;
|
||||
[mgr startCaptureWithDescriptor:desc error:&err];
|
||||
if (err)
|
||||
{
|
||||
MTLCaptureDescriptor* desc = [[MTLCaptureDescriptor new] autorelease];
|
||||
[desc setCaptureObject:m_dev.dev];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:path])
|
||||
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
|
||||
[desc setOutputURL:[NSURL fileURLWithPath:path]];
|
||||
[desc setDestination:MTLCaptureDestinationGPUTraceDocument];
|
||||
NSError* err = nullptr;
|
||||
[mgr startCaptureWithDescriptor:desc error:&err];
|
||||
if (err)
|
||||
{
|
||||
Console.Error("Metal Trace Capture failed: %s", [[err localizedDescription] UTF8String]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLn("Metal Trace Capture to /tmp/PCSX2MTLCapture.gputrace started");
|
||||
frames = 2;
|
||||
}
|
||||
Console.Error("Metal Trace Capture failed: %s", [[err localizedDescription] UTF8String]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("Metal Trace Capture Failed: MTLCaptureManager doesn't support GPU trace documents! (Did you forget to run with METAL_CAPTURE_ENABLED=1?)");
|
||||
Console.WriteLn("Metal Trace Capture to /tmp/PCSX2MTLCapture.gputrace started");
|
||||
frames = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("Metal Trace Capture Failed: MTLCaptureManager doesn't support GPU trace documents! (Did you forget to run with METAL_CAPTURE_ENABLED=1?)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -658,7 +658,6 @@
|
||||
DD0302C327C5423F0006ABDC /* PAD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5580639827AB3261008CD5D2 /* PAD.cpp */; };
|
||||
DD0302C927C549730006ABDC /* StateManagement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5580639727AB3261008CD5D2 /* StateManagement.cpp */; };
|
||||
DD03FFD827B721F20006ABDC /* GSTextureMTL.mm in Sources */ = {isa = PBXBuildFile; fileRef = DD03FFB927B70F0C0006ABDC /* GSTextureMTL.mm */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
DD03FFD927B721FC0006ABDC /* MTLDrawableFetcher.mm in Sources */ = {isa = PBXBuildFile; fileRef = DD03FFB327B70F0C0006ABDC /* MTLDrawableFetcher.mm */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
DD1134E927CBCE8F00C2E60B /* SaveState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD1134E827CBCE8900C2E60B /* SaveState.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -3198,7 +3197,6 @@
|
||||
DD0302BB27C491160006ABDC /* MetalHostDisplay.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MetalHostDisplay.mm; sourceTree = "<group>"; };
|
||||
DD0302BC27C491160006ABDC /* ContextAGL.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContextAGL.mm; sourceTree = "<group>"; };
|
||||
DD0302C827C5494A0006ABDC /* keymap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = keymap.h; sourceTree = "<group>"; };
|
||||
DD03FFB327B70F0C0006ABDC /* MTLDrawableFetcher.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTLDrawableFetcher.mm; sourceTree = "<group>"; };
|
||||
DD03FFB427B70F0C0006ABDC /* GSMetalCPPAccessible.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GSMetalCPPAccessible.h; sourceTree = "<group>"; };
|
||||
DD03FFB527B70F0C0006ABDC /* GSMTLDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GSMTLDeviceInfo.h; sourceTree = "<group>"; };
|
||||
DD03FFB627B70F0C0006ABDC /* interlace.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = interlace.metal; sourceTree = "<group>"; };
|
||||
@@ -3211,7 +3209,6 @@
|
||||
DD03FFBD27B70F0C0006ABDC /* tfx.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = tfx.metal; sourceTree = "<group>"; };
|
||||
DD03FFBE27B70F0C0006ABDC /* GSMTLSharedHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GSMTLSharedHeader.h; sourceTree = "<group>"; };
|
||||
DD03FFBF27B70F0C0006ABDC /* GSDeviceMTL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GSDeviceMTL.h; sourceTree = "<group>"; };
|
||||
DD03FFC027B70F0C0006ABDC /* MTLDrawableFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTLDrawableFetcher.h; sourceTree = "<group>"; };
|
||||
DD03FFC127B70F0C0006ABDC /* convert.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = convert.metal; sourceTree = "<group>"; };
|
||||
DD03FFCE27B719E40006ABDC /* AppConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = gui/AppConfig.h; sourceTree = "<group>"; };
|
||||
DD03FFD227B720610006ABDC /* MetalHostDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetalHostDisplay.h; sourceTree = "<group>"; };
|
||||
@@ -7571,8 +7568,6 @@
|
||||
DD03FFB927B70F0C0006ABDC /* GSTextureMTL.mm */,
|
||||
DD03FFB627B70F0C0006ABDC /* interlace.metal */,
|
||||
DD03FFB727B70F0C0006ABDC /* merge.metal */,
|
||||
DD03FFC027B70F0C0006ABDC /* MTLDrawableFetcher.h */,
|
||||
DD03FFB327B70F0C0006ABDC /* MTLDrawableFetcher.mm */,
|
||||
DD03FFBD27B70F0C0006ABDC /* tfx.metal */,
|
||||
);
|
||||
path = Metal;
|
||||
@@ -8188,7 +8183,6 @@
|
||||
551BF685264241BF0008C529 /* DisR3000A.cpp in Sources */,
|
||||
551BF690264241F10008C529 /* MipsStackWalk.cpp in Sources */,
|
||||
551BF6152642142F0008C529 /* microVU.cpp in Sources */,
|
||||
DD03FFD927B721FC0006ABDC /* MTLDrawableFetcher.mm in Sources */,
|
||||
551AA4E827937A4B00658151 /* GSDrawScanlineCodeGenerator.all.cpp in Sources */,
|
||||
551BF5AA26420FA50008C529 /* Hw.cpp in Sources */,
|
||||
551AA1792792B66400658151 /* DNS_Server.cpp in Sources */,
|
||||
|
||||
+1
-1
Submodule pcsx2 updated: 9d72b87eda...52e1255d32
Reference in New Issue
Block a user