diff --git a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm index 278761d7a4..c859146d27 100644 --- a/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm +++ b/Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm @@ -42,10 +42,10 @@ // System Frameworks #import -#if PLASMA_PIPELINE_GL +#ifdef PLASMA_PIPELINE_GL #import #endif -#if PLASMA_PIPELINE_METAL +#ifdef PLASMA_PIPELINE_METAL #import #endif #import @@ -69,11 +69,11 @@ #include "plCmdParser.h" #include "pfConsoleCore/pfConsoleEngine.h" #include "pfGameGUIMgr/pfGameGUIMgr.h" -#if PLASMA_PIPELINE_GL +#ifdef PLASMA_PIPELINE_GL #include "pfGLPipeline/plGLPipeline.h" #endif #include "plInputCore/plInputDevice.h" -#if PLASMA_PIPELINE_METAL +#ifdef PLASMA_PIPELINE_METAL #include "pfMetalPipeline/plMetalPipeline.h" #endif #include "plMessage/plDisplayScaleChangedMsg.h" @@ -468,12 +468,12 @@ - (void)startClient gClient.SetClientWindow((hsWindowHndl)(__bridge void*)self.window); gClient.SetClientDisplay((hsWindowHndl)NULL); -#if PLASMA_PIPELINE_METAL +#ifdef PLASMA_PIPELINE_METAL plMetalPipeline *pipeline = (plMetalPipeline *)gClient->GetPipeline(); pipeline->currentDrawableCallback = [self] (MTL::Device* device) { id< CAMetalDrawable > drawable; id metalDevice = (__bridge id)device; - if(((CAMetalLayer *) _renderLayer).device != metalDevice) { + if (((CAMetalLayer *) _renderLayer).device != metalDevice) { ((CAMetalLayer *) _renderLayer).device = metalDevice; dispatch_async(dispatch_get_main_queue(), ^{ [self updateWindowTitle]; @@ -488,12 +488,12 @@ - (void)startClient if (!gClient) { exit(0); } - + self.eventMonitor = [[PLSKeyboardEventMonitor alloc] initWithView:self.window.contentView inputManager:&gClient]; ((PLSView*)self.window.contentView).inputManager = gClient->GetInputManager(); [self.window makeFirstResponder:self.window.contentView]; - + // Main loop if (gClient && !gClient->GetDone()) { [self startRunLoop]; diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/Clear.metal b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/Clear.metal index 5bc3c0cbb4..7669bdc516 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/Clear.metal +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/Clear.metal @@ -70,16 +70,14 @@ vertex ClearVertexOut clearVertex(ClearVertexIn in [[ stage_in ]]) return out; } -fragment ClearFragmentOut clearFragment( - constant half4& clearColor [[ buffer(0), function_constant(ShouldClearColor) ]], - constant float& clearDepth [[ buffer(1), function_constant(ShouldClearDepth) ]] - ) +fragment ClearFragmentOut clearFragment(constant half4& clearColor [[ buffer(0), function_constant(ShouldClearColor) ]], + constant float& clearDepth [[ buffer(1), function_constant(ShouldClearDepth) ]]) { ClearFragmentOut out; - if(ShouldClearDepth) { + if (ShouldClearDepth) { out.depth = clearDepth; } - if(ShouldClearColor) { + if (ShouldClearColor) { out.color = clearColor; } return out; diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/FixedPipelineShaders.metal b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/FixedPipelineShaders.metal index e6c310aca1..2fb497d31e 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/FixedPipelineShaders.metal +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/FixedPipelineShaders.metal @@ -138,7 +138,7 @@ struct FragmentShaderArguments { texturecube cubicTexture8 [[ texture(FragmentShaderArgumentAttributeCubicTextures + 7), function_constant(hasCubicTexture8) ]]; const constant plMetalFragmentShaderArgumentBuffer* bufferedUniforms [[ buffer(FragmentShaderArgumentUniforms) ]]; half4 sampleLayer(const size_t index, const half4 vertexColor, const uint8_t passType, float3 sampleCoord) const; - //number of layers is variable, so have to declare these samplers the ugly way + // number of layers is variable, so have to declare these samplers the ugly way sampler samplers [[ sampler(0), function_constant(hasLayer1) ]]; sampler sampler2 [[ sampler(1), function_constant(hasLayer2) ]]; sampler sampler3 [[ sampler(2), function_constant(hasLayer3) ]]; @@ -160,10 +160,8 @@ typedef struct float3 texCoord6 [[function_constant(hasLayer6)]]; float3 texCoord7 [[function_constant(hasLayer7)]]; float3 texCoord8 [[function_constant(hasLayer8)]]; - //float4 normal; half4 vtxColor [[ centroid_perspective ]]; half4 fogColor; - //float4 vCamNormal; } ColorInOut; @@ -179,13 +177,12 @@ vertex ColorInOut pipelineVertexShader(Vertex in [[stage_in]], constant float4x4 & blendMatrix1 [[ buffer(VertexShaderArgumentBlendMatrix1), function_constant(temp_hasOnlyWeight1) ]]) { ColorInOut out; - //we should have been able to swizzle, but it didn't work in Xcode beta? Try again later. + // we should have been able to swizzle, but it didn't work in Xcode beta? Try again later. const half4 inColor = half4(in.color.b, in.color.g, in.color.r, in.color.a) / half4(255.0f); const half3 MAmbient = mix(inColor.rgb, uniforms.ambientCol, uniforms.ambientSrc); const half4 MDiffuse = mix(inColor, uniforms.diffuseCol, uniforms.diffuseSrc); const half3 MEmissive = mix(inColor.rgb, uniforms.emissiveCol, uniforms.emissiveSrc); - //const half4 MSpecular = half4(mix(inColor, uniforms.specularCol, uniforms.specularSrc)); half3 LAmbient = half3(0.0, 0.0, 0.0); half3 LDiffuse = half3(0.0, 0.0, 0.0); @@ -193,17 +190,17 @@ vertex ColorInOut pipelineVertexShader(Vertex in [[stage_in]], const float3 Ndirection = normalize(float4(in.normal, 0.0) * uniforms.localToWorldMatrix).xyz; float4 position = (float4(in.position, 1.0) * uniforms.localToWorldMatrix); - if(temp_hasOnlyWeight1) { + if (temp_hasOnlyWeight1) { const float4 position2 = blendMatrix1 * float4(in.position, 1.0); position = (in.weight1 * position) + ((1.0f - in.weight1) * position2); } for (size_t i = 0; i < lights.count; i++) { constant const plMetalShaderLightSource *lightSource = &lights.lampSources[i]; - if(lightSource->scale == 0.0h) + if (lightSource->scale == 0.0h) continue; - //w is attenation + // w is attenation float4 direction; if (lightSource->position.w == 0.0) { @@ -220,9 +217,9 @@ vertex ColorInOut pipelineVertexShader(Vertex in [[stage_in]], if (lightSource->spotProps.x > 0.0) { // Spot Light with cone falloff const float theta = dot(direction.xyz, normalize(-lightSource->direction).xyz); - //inner cutoff + // inner cutoff const float gamma = lightSource->spotProps.y; - //outer cutoff + // outer cutoff const float phi = lightSource->spotProps.z; const float epsilon = (gamma - phi); const float intensity = clamp((theta - phi) / epsilon, 0.0, 1.0); @@ -243,14 +240,13 @@ vertex ColorInOut pipelineVertexShader(Vertex in [[stage_in]], out.vtxColor = half4(material.rgb, abs(uniforms.invVtxAlpha - MDiffuse.a)); const float4 vCamPosition = position * uniforms.worldToCameraMatrix; - //out.vCamNormal = uniforms.worldToCameraMatrix * (uniforms.localToWorldMatrix * float4(in.position, 0.0)); - //Fog + // Fog out.fogColor = uniforms.calcFog(vCamPosition); const float4 normal = (uniforms.localToWorldMatrix * float4(in.normal, 0.0)) * uniforms.worldToCameraMatrix; - for(size_t layer=0; layeralphaThreshold) { discard_fragment(); } + if (currentColor.a < fragmentShaderArgs.bufferedUniforms->alphaThreshold) { + discard_fragment(); + } return currentColor; } @@ -516,7 +514,7 @@ constexpr void blend(half4 srcSample, thread half4 &destSample, const uint32_t b srcSample.a = srcSample.a; } - switch( blendFlags & ( kBlendAlphaAdd | kBlendAlphaMult ) ) { + switch (blendFlags & ( kBlendAlphaAdd | kBlendAlphaMult )) { case 0: destSample.a = destSample.a; break; @@ -642,12 +640,12 @@ vertex ColorInOut shadowCastVertexShader(Vertex in [[stage_in]], const float4 vCamPosition = position * uniforms.worldToCameraMatrix; - //Fog + // Fog out.fogColor = uniforms.calcFog(vCamPosition); const float4 normal = (uniforms.localToWorldMatrix * float4(in.normal, 0.0)) * uniforms.worldToCameraMatrix; - for(size_t layer=0; layer 0) { + // only possible alpha sources are layers 0 or 1 + if (alphaSrc == 0 && passCount > 0) { half4 layerColor = layers.sampleLayer(0, in.vtxColor,sourceTypes[0], in.texCoord3); currentColor.rgb *= layerColor.a; currentColor.rgb *= in.vtxColor.a; - } else if(alphaSrc == 1 && passCount > 1) { + } else if (alphaSrc == 1 && passCount > 1) { half4 layerColor = layers.sampleLayer(1, in.vtxColor, sourceTypes[1], in.texCoord3); @@ -694,9 +692,9 @@ fragment half4 shadowCastFragmentShader(ColorInOut in [[stage_in]], currentColor.rgb *= in.vtxColor.a; } - //alpha blend goes here + //a lpha blend goes here - if(currentColor.a <= 0.0h) + if (currentColor.a <= 0.0h) discard_fragment(); return currentColor; diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/GammaCorrection.metal b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/GammaCorrection.metal index 16f6d8ae92..63000b5e69 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/GammaCorrection.metal +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/GammaCorrection.metal @@ -69,11 +69,9 @@ const constant sampler lutSampler = sampler( filter::nearest ); -fragment half4 gammaCorrectFragment( - GammaVertexOut in [[stage_in]], - texture2d inputTexture [[texture(0)]], - texture1d_array LUT [[texture(1)]] - ) +fragment half4 gammaCorrectFragment(GammaVertexOut in [[stage_in]], + texture2d inputTexture [[texture(0)]], + texture1d_array LUT [[texture(1)]]) { float4 color = inputTexture.read(ushort2(in.position.xy)); return { diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/Grass.metal b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/Grass.metal index 032b186493..c3beb37f24 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/Grass.metal +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/Grass.metal @@ -10,8 +10,8 @@ using namespace metal; #include "ShaderVertex.h" -//ignoring the int and pi constants here and using whats built in -//but reserving space for them in the buffer +// ignoring the int and pi constants here and using whats built in +// but reserving space for them in the buffer typedef struct { matrix_float4x4 Local2NDC; float4 intConstants; @@ -80,7 +80,7 @@ fragment half4 ps_GrassShader(vs_GrassInOut in [[stage_in]], half4 out = t0.sample(colorSampler, in.texCoord.xy); out *= half4(in.color); - if(out.a <= 0.1) + if (out.a <= 0.1) discard_fragment(); return out; } diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/ShaderTypes.h b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/ShaderTypes.h index 0269390866..e0375ed9a9 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/ShaderTypes.h +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/ShaderTypes.h @@ -152,13 +152,13 @@ typedef struct typedef struct { - //transformation + // transformation matrix_float4x4 projectionMatrix; matrix_float4x4 localToWorldMatrix; matrix_float4x4 cameraToWorldMatrix; matrix_float4x4 worldToCameraMatrix; - //lighting + // lighting half4 globalAmb; half3 ambientCol; uint8_t ambientSrc; diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/TextFontShader.metal b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/TextFontShader.metal index 8d07e91daa..89513a03eb 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/TextFontShader.metal +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/TextFontShader.metal @@ -85,7 +85,7 @@ vertex ColorInOut textFontVertexShader(constant Vertex *in [[ buffer(0) ]], } fragment half4 textFontFragmentShader(ColorInOut in [[stage_in]], - texture2d colorMap [[ texture(0) ]]) + texture2d colorMap [[ texture(0) ]]) { constexpr sampler colorSampler(mip_filter::nearest, mag_filter::nearest, diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/WaveSet7.metal b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/WaveSet7.metal index a587a56473..04998c3d8e 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/WaveSet7.metal +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/ShaderSrc/WaveSet7.metal @@ -349,7 +349,7 @@ vertex vs_WaveFixedFin7InOut vs_WaveFixedFin7(Vertex in [[stage_in]], float3 D = r5.xyz; float3 F = uniforms.EnvAdjust.xyz; float G = uniforms.EnvAdjust.w; - //METAL NOTE: HLSL 1.1 always applies an abs operation to values it's about to sqrt + // METAL NOTE: HLSL 1.1 always applies an abs operation to values it's about to sqrt float3 t = dot(D.xyz, F.xyz) + sqrt(abs(pow(abs(dot(D.xyz, F.xyz)), 2) - G));// r10.z = D dot F + SQRT((D dot F)^2 - G) r0.xyz = (D * t) - F; // r0.xyz = D * t - (envCenter - camPos) } diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.cpp b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.cpp index 1c8371d743..8f14e4fc4d 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.cpp +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.cpp @@ -40,27 +40,26 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com *==LICENSE==*/ -#ifndef plMetalDevice_hpp -#define plMetalDevice_hpp - -// We need to define these once for Metal somewhere in a cpp file +// We need to define these once and only one for Metal somewhere +// in a cpp file before the Metal-cpp include (via plMetalDevice) #define NS_PRIVATE_IMPLEMENTATION #define CA_PRIVATE_IMPLEMENTATION #define MTL_PRIVATE_IMPLEMENTATION #include "plMetalDevice.h" -#include - -#include "ShaderTypes.h" +#include "hsDarwin.h" #include "hsThread.h" + #include "plDrawable/plGBufferGroup.h" #include "plGImage/plCubicEnvironmap.h" #include "plGImage/plMipmap.h" -#include "plMetalPipeline.h" -#include "plMetalPipelineState.h" #include "plPipeline/plRenderTarget.h" +#include "pfMetalPipeline/plMetalPipeline.h" +#include "pfMetalPipeline/plMetalPipelineState.h" +#include "pfMetalPipeline/ShaderSrc/ShaderTypes.h" + matrix_float4x4* hsMatrix2SIMD(const hsMatrix44& src, matrix_float4x4* dst) { if (src.fFlags & hsMatrix44::kIsIdent) { @@ -215,9 +214,7 @@ void plMetalDevice::Clear(bool shouldClearColor, simd_float4 clearColor, bool sh void plMetalDevice::BeginNewRenderPass() { - // printf("Beginning new render pass\n"); - - // lazilly create the screen render encoder if it does not yet exist + // lazily create the screen render encoder if it does not yet exist if (!fCurrentOffscreenCommandBuffer && !fCurrentRenderTargetCommandEncoder) { SetRenderTarget(nullptr); } @@ -228,7 +225,7 @@ void plMetalDevice::BeginNewRenderPass() // pass descriptor and submit more commands fCurrentRenderTargetCommandEncoder->endEncoding(); fCurrentRenderTargetCommandEncoder->release(); - fCurrentRenderTargetCommandEncoder = nil; + fCurrentRenderTargetCommandEncoder = nullptr; } MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::renderPassDescriptor(); @@ -309,7 +306,7 @@ void plMetalDevice::SetRenderTarget(plRenderTarget* target) // pass descriptor and submit more commands fCurrentRenderTargetCommandEncoder->endEncoding(); fCurrentRenderTargetCommandEncoder->release(); - fCurrentRenderTargetCommandEncoder = nil; + fCurrentRenderTargetCommandEncoder = nullptr; } if (fCurrentOffscreenCommandBuffer) { @@ -326,7 +323,7 @@ void plMetalDevice::SetRenderTarget(plRenderTarget* target) fCurrentOffscreenCommandBuffer->waitUntilCompleted(); } fCurrentOffscreenCommandBuffer->release(); - fCurrentOffscreenCommandBuffer = nil; + fCurrentOffscreenCommandBuffer = nullptr; } fCurrentRenderTarget = target; @@ -359,23 +356,23 @@ void plMetalDevice::SetRenderTarget(plRenderTarget* target) } plMetalDevice::plMetalDevice() - : fErrorMsg(nullptr), + : fErrorMsg(), fActiveThread(hsThread::ThisThreadHash()), - fCurrentDrawable(nullptr), - fCommandQueue(nullptr), - fCurrentRenderTargetCommandEncoder(nullptr), - fCurrentDrawableDepthTexture(nullptr), - fCurrentFragmentOutputTexture(nullptr), - fCurrentCommandBuffer(nullptr), - fCurrentOffscreenCommandBuffer(nullptr), - fCurrentRenderTarget(nullptr), + fCurrentDrawable(), + fCommandQueue(), + fCurrentRenderTargetCommandEncoder(), + fCurrentDrawableDepthTexture(), + fCurrentFragmentOutputTexture(), + fCurrentCommandBuffer(), + fCurrentOffscreenCommandBuffer(), + fCurrentRenderTarget(), fNewPipelineStateMap(), - fCurrentFragmentMSAAOutputTexture(nullptr), - fCurrentUnprocessedOutputTexture(nullptr), - fGammaLUTTexture(nullptr), - fGammaAdjustState(nullptr), - fBlitCommandBuffer(nullptr), - fBlitCommandEncoder(nullptr) + fCurrentFragmentMSAAOutputTexture(), + fCurrentUnprocessedOutputTexture(), + fGammaLUTTexture(), + fGammaAdjustState(), + fBlitCommandBuffer(), + fBlitCommandEncoder() { fClearRenderTargetColor = {0.0, 0.0, 0.0, 1.0}; fClearDrawableColor = {0.0, 0.0, 0.0, 1.0}; @@ -541,7 +538,7 @@ void plMetalDevice::FillVertexBufferRef(VertexBufferRef* ref, plGBufferGroup* gr /// Interleaved, do straight copy memcpy(ptr, srcVPtr + cell->fVtxStart, cell->fLength * vertSize); ptr += cell->fLength * vertSize; - assert(size <= cell->fLength * vertSize); + hsAssert(size <= cell->fLength * vertSize, "Interleaved copy size mismatch"); } else { hsStatusMessage("Non interleaved data"); @@ -714,11 +711,11 @@ void plMetalDevice::ReleaseFramebufferObjects() { if (fCurrentUnprocessedOutputTexture) fCurrentUnprocessedOutputTexture->release(); - fCurrentFragmentOutputTexture = nil; + fCurrentFragmentOutputTexture = nullptr; if (fGammaAdjustState) fGammaAdjustState->release(); - fGammaAdjustState = nil; + fGammaAdjustState = nullptr; } void plMetalDevice::SetFramebufferFormat(MTL::PixelFormat format) @@ -811,7 +808,7 @@ void plMetalDevice::PopulateTexture(plMetalDevice::TextureRef* tRef, plMipmap* i }; RGBA4444Component* in = (RGBA4444Component*)img->GetCurrLevelPtr(); - simd_uint4* out = (simd_uint4*)malloc(img->GetCurrHeight() * img->GetCurrWidth() * 4); + auto out = std::make_unique(img->GetCurrHeight() * img->GetCurrWidth()); for (int i = 0; i < (img->GetCurrWidth() * img->GetCurrHeight()); i++) { out[i].r = in[i].r; @@ -820,18 +817,19 @@ void plMetalDevice::PopulateTexture(plMetalDevice::TextureRef* tRef, plMipmap* i out[i].a = in[i].a; } - tRef->fTexture->replaceRegion(MTL::Region::Make2D(0, 0, img->GetCurrWidth(), img->GetCurrHeight()), img->GetCurrLevel(), slice, out, img->GetCurrWidth() * 4, 0); - - free(out); + tRef->fTexture->replaceRegion(MTL::Region::Make2D(0, 0, img->GetCurrWidth(), img->GetCurrHeight()), img->GetCurrLevel(), slice, out.get(), img->GetCurrWidth() * 4, 0); } else { tRef->fTexture->replaceRegion(MTL::Region::Make2D(0, 0, img->GetCurrWidth(), img->GetCurrHeight()), img->GetCurrLevel(), slice, img->GetCurrLevelPtr(), img->GetCurrWidth() * 4, 0); } } else { - printf("Texture with no image data?\n"); + hsAssert(0, "Texture with no image data?\n"); } } } - tRef->fTexture->setLabel(NS::String::string(img->GetKeyName().c_str(), NS::UTF8StringEncoding)); + + CFStringRef name = CFStringCreateWithSTString(img->GetKeyName()); + tRef->fTexture->setLabel(reinterpret_cast(name)); + CFRelease(name); tRef->SetDirty(false); } @@ -882,7 +880,7 @@ void plMetalDevice::MakeCubicTextureRef(plMetalDevice::TextureRef* tRef, plCubic tRef->fTexture = fMetalDevice->newTexture(descriptor); - static const uint kFaceMapping[] = { + static constexpr uint kFaceMapping[] = { 1, // kLeftFace 0, // kRightFace 4, // kFrontFace @@ -993,13 +991,12 @@ void plMetalDevice::CreateNewCommandBuffer(CA::MetalDrawable* drawable) void plMetalDevice::StartPipelineBuild(plMetalPipelineRecord& record, std::condition_variable** condOut) { - __block std::condition_variable* newCondition = new std::condition_variable(); - fConditionMap[record] = newCondition; + fConditionMap[record] = new std::condition_variable(); if (condOut) { - *condOut = newCondition; + *condOut = fConditionMap[record]; } - if (fNewPipelineStateMap[record] != NULL) { + if (fNewPipelineStateMap[record] != nullptr) { // The shader is already compiled. return; } @@ -1042,7 +1039,7 @@ void plMetalDevice::StartPipelineBuild(plMetalPipelineRecord& record, std::condi fNewPipelineStateMap[record] = linkedPipeline; // signal that we're done - newCondition->notify_all(); + fConditionMap[record]->notify_all(); } }); @@ -1156,10 +1153,10 @@ void plMetalDevice::SubmitCommandBuffer() fCurrentCommandBuffer->presentDrawable(fCurrentDrawable); fCurrentCommandBuffer->commit(); fCurrentCommandBuffer->release(); - fCurrentCommandBuffer = nil; + fCurrentCommandBuffer = nullptr; fCurrentDrawable->release(); - fCurrentDrawable = nil; + fCurrentDrawable = nullptr; // Reset the clear colors for the next pass // Metal clears on framebuffer load - so don't cause a clear @@ -1225,9 +1222,9 @@ void plMetalDevice::PostprocessIntoDrawable() gammaAdjustEncoder->endEncoding(); } -std::size_t plMetalDevice::plMetalPipelineRecordHashFunction ::operator()(plMetalPipelineRecord const& s) const noexcept +size_t plMetalDevice::plMetalPipelineRecordHashFunction ::operator()(plMetalPipelineRecord const& s) const noexcept { - std::size_t value = std::hash()(s.depthFormat); + size_t value = std::hash()(s.depthFormat); value ^= std::hash()(s.colorFormat); value ^= std::hash()(*s.state); value ^= std::hash()(s.sampleCount); @@ -1276,5 +1273,3 @@ void plMetalDevice::BlitTexture(MTL::Texture* src, MTL::Texture* dst) fBlitCommandEncoder->copyFromTexture(src, 0, 0, MTL::Origin(0, 0, 0), MTL::Size(src->width(), src->height(), 0), dst, 0, 0, MTL::Origin(0, 0, 0)); } - -#endif diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.h b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.h index 8abaeef984..84767ca168 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.h +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.h @@ -246,7 +246,7 @@ class plMetalDevice MTL::CommandBuffer* fBlitCommandBuffer; MTL::BlitCommandEncoder* fBlitCommandEncoder; - bool NeedsPostprocessing() + bool NeedsPostprocessing() const { return fGammaLUTTexture != nullptr; } diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRef.cpp b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRef.cpp deleted file mode 100644 index 373043be70..0000000000 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRef.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// plMetalDeviceRef.cpp -// CoreLib -// -// Created by Colin Cornaby on 11/10/21. -// - -#include "plMetalDeviceRef.h" - -void plMetalDeviceRef::Unlink() -{ - hsAssert(fBack, "plGLDeviceRef not in list"); - - if (fNext) - fNext->fBack = fBack; - *fBack = fNext; - - fBack = nullptr; - fNext = nullptr; -} - -void plMetalDeviceRef::Link(plMetalDeviceRef **back) -{ - hsAssert(fNext == nullptr && fBack == nullptr, "Trying to link a plMetalDeviceRef that's already linked"); - - fNext = *back; - if (*back) - (*back)->fBack = &fNext; - fBack = back; - *back = this; -} - -plMetalDeviceRef::~plMetalDeviceRef() -{ - if (fNext != nullptr || fBack != nullptr) - Unlink(); -} - -plMetalVertexBufferRef::~plMetalVertexBufferRef() -{ - Release(); -} - -void plMetalVertexBufferRef::Release() -{ - SetDirty(true); -} - -plMetalTextureRef::~plMetalTextureRef() -{ - // fTexture->release(); - Release(); -} - -void plMetalTextureRef::Release() -{ - SetDirty(true); -} - -plMetalIndexBufferRef::~plMetalIndexBufferRef() -{ - Release(); -} - -void plMetalIndexBufferRef::Release() -{ - SetDirty(true); -} - -plMetalRenderTargetRef::~plMetalRenderTargetRef() -{ - Release(); -} - -void plMetalRenderTargetRef::Release() -{ - SetDirty(true); -} diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRef.h b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRef.h index e30df0db03..c7608d6aad 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRef.h +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRef.h @@ -80,11 +80,20 @@ class plMetalDeviceRef : public hsGDeviceRef }; /* - The buffer pool stores and recycles buffers so that Plasma can encode GPU commands and render in parallel. That means we can't touch buffers the GPU is using, and if a pass or frame rewrites a buffer we have to make sure it's not stomping on something that is already attached to a frame. Because Metal can triple buffer, the first dimension of caching is hard coded to 3. Some ages will also rewrite buffers an unspecified number of times between render passes. For example: A reflection render and a main render might have different index buffers. So the second dimension of caching uses an unbounded vector that will hold enough buffers to render in any one age. - - Buffer pools do not allocate buffers, they only store them. The outside caller is responsible for allocating a buffer and then setting it. The buffer pool will retain any buffers within the pool, and automatically release them when they are overwritten or the pool is deallocated. - - Because buffers are only stored on write, and no allocations happen within the pool, overhead is kept low for static buffers. Completely static buffers will never expand the pool if they only write once. + The buffer pool stores and recycles buffers so that Plasma can encode GPU commands and render in + parallel. That means we can't touch buffers the GPU is using, and if a pass or frame rewrites a + buffer we have to make sure it's not stomping on something that is already attached to a frame. + Because Metal can triple buffer, the first dimension of caching is hard coded to 3. Some ages + will also rewrite buffers an unspecified number of times between render passes. For example: A r + eflection render and a main render might have different index buffers. So the second dimension of + caching uses an unbounded vector that will hold enough buffers to render in any one age. + + Buffer pools do not allocate buffers, they only store them. The outside caller is responsible for + allocating a buffer and then setting it. The buffer pool will retain any buffers within the pool, + and automatically release them when they are overwritten or the pool is deallocated. + + Because buffers are only stored on write, and no allocations happen within the pool, overhead is + kept low for static buffers. Completely static buffers will never expand the pool if they only write once. */ class plMetalBufferPoolRef : public plMetalDeviceRef { @@ -94,10 +103,10 @@ class plMetalBufferPoolRef : public plMetalDeviceRef uint32_t fLastWriteFrameTime; plMetalBufferPoolRef() : plMetalDeviceRef(), - fLastWriteFrameTime(0), - fCurrentPass(0), - fCurrentFrame(0), - fBuffer(nullptr) + fLastWriteFrameTime(), + fCurrentPass(), + fCurrentFrame(), + fBuffer() { } @@ -124,7 +133,7 @@ class plMetalBufferPoolRef : public plMetalDeviceRef static void SetFrameTime(uint32_t frameTime) { fFrameTime = frameTime; }; - MTL::Buffer* GetBuffer() { return fBuffer; }; + MTL::Buffer* GetBuffer() const { return fBuffer; }; void SetBuffer(MTL::Buffer* buffer) { @@ -189,21 +198,21 @@ class plMetalVertexBufferRef : public plMetalBufferPoolRef void SetRefTime(uint32_t t) { fRefTime = t; } plMetalVertexBufferRef() : plMetalBufferPoolRef(), - fCount(0), - fIndex(0), - fVertexSize(0), - fOffset(0), - fOwner(nullptr), - fData(nullptr), - fFormat(0), - fRefTime(0) + fCount(), + fIndex(), + fVertexSize(), + fOffset(), + fOwner(), + fData(), + fFormat(), + fRefTime() { } virtual ~plMetalVertexBufferRef(); void Link(plMetalVertexBufferRef** back) { plMetalDeviceRef::Link((plMetalDeviceRef**)back); } - plMetalVertexBufferRef* GetNext() { return (plMetalVertexBufferRef*)fNext; } + plMetalVertexBufferRef* GetNext() const { return (plMetalVertexBufferRef*)fNext; } void Release() override; }; @@ -239,11 +248,11 @@ class plMetalIndexBufferRef : public plMetalBufferPoolRef virtual ~plMetalIndexBufferRef(); plMetalIndexBufferRef() : plMetalBufferPoolRef(), - fCount(0), - fIndex(0), - fRefTime(0), - fLastWriteFrameTime(0), - fOwner(nullptr) + fCount(), + fIndex(), + fRefTime(), + fLastWriteFrameTime(), + fOwner() { } }; @@ -258,11 +267,11 @@ class plMetalTextureRef : public plMetalDeviceRef MTL::PixelFormat fFormat; void Link(plMetalTextureRef** back) { plMetalDeviceRef::Link((plMetalDeviceRef**)back); } - plMetalTextureRef* GetNext() { return (plMetalTextureRef*)fNext; } + plMetalTextureRef* const GetNext() { return (plMetalTextureRef*)fNext; } plMetalTextureRef() : plMetalDeviceRef(), - fOwner(nullptr), - fTexture(nullptr), + fOwner(), + fTexture(), fLevels(1) { } diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRefs.cpp b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRefs.cpp index 81233adbdc..87d4f6181a 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRefs.cpp +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDeviceRefs.cpp @@ -53,8 +53,8 @@ plProfile_CreateMemCounter("Textures", "Memory", MemTexture); ** Generic plGLDeviceRef Functions ** *****************************************************************************/ plMetalDeviceRef::plMetalDeviceRef() - : fNext(nullptr), - fBack(nullptr) + : fNext(), + fBack() { } @@ -95,8 +95,7 @@ void plMetalDeviceRef::Link(plMetalDeviceRef **back) plMetalVertexBufferRef::~plMetalVertexBufferRef() { - if (fData) - delete fData; + delete fData; Release(); } diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalEnumerate.h b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalEnumerate.h deleted file mode 100644 index 3628b91368..0000000000 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalEnumerate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// plMetalEnumerate.hpp -// pfMetalPipeline -// -// Created by Colin Cornaby on 3/20/22. -// - -#ifndef plMetalEnumerate_hpp -#define plMetalEnumerate_hpp - -#include - -#endif /* plMetalEnumerate_hpp */ diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalFragmentShader.cpp b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalFragmentShader.cpp index a3f84bf7ff..8b0c886033 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalFragmentShader.cpp +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalFragmentShader.cpp @@ -61,9 +61,7 @@ plMetalFragmentShader::~plMetalFragmentShader() void plMetalFragmentShader::Release() { - fPipe = nil; - - // ISetError(nil); + fPipe = nullptr; } bool plMetalFragmentShader::ISetConstants(plMetalPipeline* pipe) diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalFragmentShader.h b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalFragmentShader.h index 427469a7ee..10a1ccbcae 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalFragmentShader.h +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalFragmentShader.h @@ -56,9 +56,9 @@ class plMetalFragmentShader : public plMetalShader plMetalFragmentShader(plShader* owner); virtual ~plMetalFragmentShader(); - void Release() override; + void Release() override; void Link(plMetalFragmentShader** back) { plMetalDeviceRef::Link((plMetalDeviceRef**)back); } - plMetalFragmentShader* GetNext() { return (plMetalFragmentShader*)fNext; } + plMetalFragmentShader* const GetNext() { return (plMetalFragmentShader*)fNext; } }; #endif // plMetalFragmentShader_inc diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalMaterialShaderRef.cpp b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalMaterialShaderRef.cpp index ddf4568e31..4b0498e613 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalMaterialShaderRef.cpp +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalMaterialShaderRef.cpp @@ -42,11 +42,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plMetalMaterialShaderRef.h" -#include - #include "HeadSpin.h" #include "hsBitVector.h" #include "hsGMatState.inl" + #include "plDrawable/plGBufferGroup.h" #include "plGImage/plCubicEnvironmap.h" #include "plGImage/plMipmap.h" @@ -59,10 +58,12 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plSurface/hsGMaterial.h" #include "plSurface/plLayerInterface.h" -plMetalMaterialShaderRef::plMetalMaterialShaderRef(hsGMaterial* mat, plMetalPipeline* pipe) : fPipeline{pipe}, - fMaterial{mat}, +#include + +plMetalMaterialShaderRef::plMetalMaterialShaderRef(hsGMaterial* mat, plMetalPipeline* pipe) : fPipeline(pipe), + fMaterial(mat), fFragFunction(), - fNumPasses(0) + fNumPasses() { fDevice = pipe->fDevice.fMetalDevice; fFragFunction = pipe->fFragFunction; @@ -78,7 +79,7 @@ void plMetalMaterialShaderRef::Release() { for (auto& buffer : fPassArgumentBuffers) { buffer->release(); - buffer = nil; + buffer = nullptr; } fPassArgumentBuffers.clear(); @@ -154,7 +155,7 @@ void plMetalMaterialShaderRef::FastEncodeArguments(MTL::RenderCommandEncoder* en // continue; // } - assert(i - GetPassIndex(pass) >= 0); + hsAssert(i - GetPassIndex(pass) >= 0, "Bad pass index during encode"); EncodeTransform(layer, &vertexUniforms->uvTransforms[i - GetPassIndex(pass)]); IBuildLayerTexture(encoder, i - GetPassIndex(pass), layer); } @@ -162,7 +163,12 @@ void plMetalMaterialShaderRef::FastEncodeArguments(MTL::RenderCommandEncoder* en encoder->setFragmentBuffer(fPassArgumentBuffers[pass], 0, FragmentShaderArgumentUniforms); } -void plMetalMaterialShaderRef::EncodeArguments(MTL::RenderCommandEncoder* encoder, VertexUniforms* vertexUniforms, uint pass, plMetalFragmentShaderDescription* passDescription, std::vector* piggyBacks, std::function preEncodeTransform, std::function postEncodeTransform) +void plMetalMaterialShaderRef::EncodeArguments(MTL::RenderCommandEncoder* encoder, + VertexUniforms* vertexUniforms, uint pass, + plMetalFragmentShaderDescription* passDescription, + std::vector* piggyBacks, + std::function preEncodeTransform, + std::function postEncodeTransform) { std::vector layers = GetLayersForPass(pass); @@ -174,7 +180,7 @@ void plMetalMaterialShaderRef::EncodeArguments(MTL::RenderCommandEncoder* encode IHandleMaterial( GetPassIndex(pass), passDescription, &uniforms, piggyBacks, - [&](plLayerInterface* layer, uint32_t index) { + [this, &preEncodeTransform, &encoder, &pass, &vertexUniforms](plLayerInterface* layer, uint32_t index) { layer = preEncodeTransform(layer, index); IBuildLayerTexture(encoder, index, layer); @@ -184,10 +190,8 @@ void plMetalMaterialShaderRef::EncodeArguments(MTL::RenderCommandEncoder* encode EncodeTransform(layer, &vertexUniforms->uvTransforms[index]); return layer; - }, - [&](plLayerInterface* layer, uint32_t index) { - layer = postEncodeTransform(layer, index); - return layer; + }, [&postEncodeTransform](plLayerInterface* layer, uint32_t index) { + return postEncodeTransform(layer, index); }); encoder->setFragmentBytes(&uniforms, sizeof(plMetalFragmentShaderArgumentBuffer), FragmentShaderArgumentUniforms); @@ -253,8 +257,7 @@ void plMetalMaterialShaderRef::ILoopOverLayers() currLayer, &passDescription, layerBuffer, nullptr, [](plLayerInterface* layer, uint32_t index) { return layer; - }, - [](plLayerInterface* layer, uint32_t index) { + }, [](plLayerInterface* layer, uint32_t index) { return layer; }); @@ -291,7 +294,7 @@ void plMetalMaterialShaderRef::ILoopOverLayers() } } -const hsGMatState plMetalMaterialShaderRef::ICompositeLayerState(const plLayerInterface* layer) +const hsGMatState plMetalMaterialShaderRef::ICompositeLayerState(const plLayerInterface* layer) const { hsGMatState state; state.Composite(layer->GetState(), fPipeline->GetMaterialOverride(true), fPipeline->GetMaterialOverride(false)); @@ -402,7 +405,12 @@ bool plMetalMaterialShaderRef::ICanEatLayer(plLayerInterface* lay) return true; } -uint32_t plMetalMaterialShaderRef::IHandleMaterial(uint32_t layer, plMetalFragmentShaderDescription* passDescription, plMetalFragmentShaderArgumentBuffer* uniforms, std::vector* piggybacks, const std::function& preEncodeTransform, const std::function& postEncodeTransform) +uint32_t plMetalMaterialShaderRef::IHandleMaterial(uint32_t layer, + plMetalFragmentShaderDescription* passDescription, + plMetalFragmentShaderArgumentBuffer* uniforms, + std::vector* piggybacks, + const std::function& preEncodeTransform, + const std::function& postEncodeTransform) { if (!fMaterial || layer >= fMaterial->GetNumLayers() || !fMaterial->GetLayer(layer)) { return -1; @@ -422,7 +430,7 @@ uint32_t plMetalMaterialShaderRef::IHandleMaterial(uint32_t layer, plMetalFragme // Ignoring the bit about self-rendering cube maps - plLayerInterface* currLay = /*IPushOverBaseLayer*/ fMaterial->GetLayer(layer); + plLayerInterface* currLay = fMaterial->GetLayer(layer); currLay = preEncodeTransform(currLay, 0); if (fPipeline->IsDebugFlagSet(plPipeDbg::kFlagBumpW) && (currLay->GetMiscFlags() & hsGMatState::kMiscBumpDu)) { @@ -501,7 +509,7 @@ uint32_t plMetalMaterialShaderRef::IHandleMaterial(uint32_t layer, plMetalFragme } } - passDescription->numLayers = (piggybacks ? piggybacks->size() : 0) + currNumLayers; + passDescription->fNumLayers = (piggybacks ? piggybacks->size() : 0) + currNumLayers; if (state.fBlendFlags & (hsGMatState::kBlendTest | hsGMatState::kBlendAlpha | hsGMatState::kBlendAddColorTimesAlpha) && !(state.fBlendFlags & hsGMatState::kBlendAlphaAlways)) { diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalMaterialShaderRef.h b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalMaterialShaderRef.h index e1830ba7a6..84b7eea0e4 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalMaterialShaderRef.h +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalMaterialShaderRef.h @@ -70,7 +70,7 @@ class plMetalMaterialShaderRef : public plMetalDeviceRef public: void Link(plMetalMaterialShaderRef **back) { plMetalDeviceRef::Link((plMetalDeviceRef **)back); } - plMetalMaterialShaderRef *GetNext() { return (plMetalMaterialShaderRef *)fNext; } + plMetalMaterialShaderRef* GetNext() const { return (plMetalMaterialShaderRef *)fNext; } plMetalMaterialShaderRef(hsGMaterial *mat, plMetalPipeline *pipe); ~plMetalMaterialShaderRef(); @@ -81,9 +81,15 @@ class plMetalMaterialShaderRef : public plMetalDeviceRef uint32_t GetNumPasses() const { return fNumPasses; } uint32_t GetPassIndex(size_t which) const { return fPassIndices[which]; } - const std::vector GetLayersForPass(size_t pass) { return fPasses[pass]; } - - void EncodeArguments(MTL::RenderCommandEncoder *encoder, VertexUniforms *vertexUniforms, uint pass, plMetalFragmentShaderDescription *passDescription, std::vector *piggyBacks, std::function preEncodeTransform, std::function postEncodeTransform); + const std::vector GetLayersForPass(size_t pass) const { return fPasses[pass]; } + + void EncodeArguments(MTL::RenderCommandEncoder *encoder, + VertexUniforms *vertexUniforms, + uint pass, + plMetalFragmentShaderDescription *passDescription, + std::vector *piggyBacks, + std::function preEncodeTransform, + std::function postEncodeTransform); void FastEncodeArguments(MTL::RenderCommandEncoder *encoder, VertexUniforms *vertexUniforms, uint pass); // probably not a good idea to call prepareTextures directly // mostly just a hack to keep plates working for now @@ -93,9 +99,9 @@ class plMetalMaterialShaderRef : public plMetalDeviceRef // Set the current Plasma state based on the input layer state and the material overrides. // fMatOverOn overrides to set a state bit whether it is set in the layer or not. // fMatOverOff overrides to clear a state bit whether it is set in the layer or not.s - const hsGMatState ICompositeLayerState(const plLayerInterface *layer); + const hsGMatState ICompositeLayerState(const plLayerInterface *layer) const; - const struct plMetalFragmentShaderDescription GetFragmentShaderDescription(size_t which) + const struct plMetalFragmentShaderDescription GetFragmentShaderDescription(size_t which) const { return fFragmentShaderDescriptions[which]; } @@ -104,13 +110,18 @@ class plMetalMaterialShaderRef : public plMetalDeviceRef void ILoopOverLayers(); uint32_t fNumPasses; - uint32_t IHandleMaterial(uint32_t layer, plMetalFragmentShaderDescription *passDescription, plMetalFragmentShaderArgumentBuffer *uniforms, std::vector *piggybacks, const std::function& preEncodeTransform, const std::function& postEncodeTransform); + uint32_t IHandleMaterial(uint32_t layer, + plMetalFragmentShaderDescription* passDescription, + plMetalFragmentShaderArgumentBuffer* uniforms, + std::vector* piggybacks, + const std::function& preEncodeTransform, + const std::function& postEncodeTransform); bool ICanEatLayer(plLayerInterface *lay); uint32_t ILayersAtOnce(uint32_t which); - void IBuildLayerTexture(MTL::RenderCommandEncoder *encoder, uint32_t offsetFromRootLayer, plLayerInterface *layer); - void EncodeTransform(plLayerInterface *layer, UVOutDescriptor *transform); - std::vector> fPasses; + void IBuildLayerTexture(MTL::RenderCommandEncoder* encoder, uint32_t offsetFromRootLayer, plLayerInterface* layer); + void EncodeTransform(plLayerInterface* layer, UVOutDescriptor *transform); + std::vector> fPasses; std::vector fFragmentShaderDescriptions; }; diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipeline.cpp b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipeline.cpp index 570830dd00..d2dfeada91 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipeline.cpp +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipeline.cpp @@ -49,6 +49,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "HeadSpin.h" #include "hsGMatState.inl" #include "hsTimer.h" + #include "pfCamera/plVirtualCamNeu.h" #include "plAvatar/plAvatarClothing.h" #include "plDrawable/plAuxSpan.h" @@ -79,6 +80,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plSurface/plLayerShadowBase.h" #include "plTweak.h" #include "plgDispatch.h" + #include "pnMessage/plPipeResMakeMsg.h" #include "pnNetCommon/plNetApp.h" // for dbg logging @@ -160,12 +162,12 @@ bool plRenderTriListFunc::RenderPrims() const plMetalPipeline::plMetalPipeline(hsWindowHndl display, hsWindowHndl window, const hsG3DDeviceModeRecord* devMode) : pl3DPipeline(devMode), fRenderTargetRefList(), fMatRefList(), - fCurrentRenderPassUniforms(nullptr), - currentDrawableCallback(nullptr), - fFragFunction(nullptr), - fVShaderRefList(nullptr), - fPShaderRefList(nullptr), - fULutTextureRef(nullptr), + fCurrentRenderPassUniforms(), + currentDrawableCallback(), + fFragFunction(), + fVShaderRefList(), + fPShaderRefList(), + fULutTextureRef(), fCurrRenderLayer() { fTextureRefList = nullptr; @@ -274,7 +276,8 @@ plTextFont* plMetalPipeline::MakeTextFont(ST::string face, uint16_t size) bool plMetalPipeline::OpenAccess(plAccessSpan& dst, plDrawableSpans* d, const plVertexSpan* span, bool readOnly) { - // FIXME: Whats this? + // FIXME: What's this? + // Hoikas: It's for runtime reading/writing the vertices, mostly used by stuff like dynamic decals. return false; } @@ -376,7 +379,8 @@ hsGDeviceRef* plMetalPipeline::MakeRenderTargetRef(plRenderTarget* owner) plCubicRenderTarget* cubicRT; // If we have Shader Model 3 and support non-POT textures, let's make reflections the pipe size - if (plDynamicCamMap* camMap = plDynamicCamMap::ConvertNoRef(owner)) { + plDynamicCamMap* camMap = plDynamicCamMap::ConvertNoRef(owner); + if (camMap && camMap->IsReflection()) { camMap->ResizeViewport(IGetViewTransform()); } @@ -432,7 +436,7 @@ hsGDeviceRef* plMetalPipeline::MakeRenderTargetRef(plRenderTarget* owner) plRenderTarget* face = cubicRT->GetFace(i); plMetalRenderTargetRef* fRef; - if (face->GetDeviceRef() != nil) { + if (face->GetDeviceRef() != nullptr) { fRef = (plMetalRenderTargetRef*)face->GetDeviceRef(); if (!fRef->IsLinked()) fRef->Link(&fRenderTargetRefList); @@ -956,13 +960,21 @@ void plMetalPipeline::GetSupportedDisplayModes(std::vector* res, /* There are decisions to make here. - Modern macOS does not support "display modes." You panel runs at native resolution at all times, and you can over-render or under-render. But you never set the display mode of the panel, or get the display mode of the panel. Most games have a "scale slider." + Modern macOS does not support "display modes." You panel runs at native resolution at all times, + and you can over-render or under-render. But you never set the display mode of the panel, or get + the display mode of the panel. Most games have a "scale slider." - Note: There are legacy APIs for display modes for compatibility with older software. In since we're here writing a new renderer, lets do things the right way. The display mode APIs also have trouble with density. I.E. a 4k display might be reported as a 2k display if the window manager is running in a higher DPI mode. + Note: There are legacy APIs for display modes for compatibility with older software. In since + we're here writing a new renderer, lets do things the right way. The display mode APIs also have + trouble with density. I.E. a 4k display might be reported as a 2k display if the window manager is + running in a higher DPI mode. - The basic approach should be to render at whatever the resolution of our output surface is. We're mostly doing that now (aspect ratio doesn't adjust.) + The basic approach should be to render at whatever the resolution of our output surface is. We're + mostly doing that now (aspect ratio doesn't adjust.) - Ideally we should support some sort of scaling/semi dynamic renderbuffer resolution thing. But don't mess with the window servers framebuffer size. macOS has accelerated resolution scaling like consoles do. Use that. + Ideally we should support some sort of scaling/semi dynamic renderbuffer resolution thing. But don't + mess with the window servers framebuffer size. macOS has accelerated resolution scaling like consoles + do. Use that. */ std::vector supported; @@ -999,7 +1011,7 @@ int plMetalPipeline::GetMaxAntiAlias(int Width, int Height, int ColorDepth) void plMetalPipeline::ResetDisplayDevice(int Width, int Height, int ColorDepth, bool Windowed, int NumAASamples, int MaxAnisotropicSamples, bool vSync) { - // FIXME: Whats this? + // FIXME: What's this? // Seems like an entry point for passing in display settings. fDevice.SetMaxAnsiotropy(MaxAnisotropicSamples); @@ -1310,14 +1322,13 @@ void plMetalPipeline::IRenderProjection(const plRenderPrimFunc& render, plLightI IHandleZMode(hsGMatState::kZNoZWrite); // This is a bit weird - in since this isn't a material we need to build a query for the right Metal program ourselves - plMetalFragmentShaderDescription description; - memset(&description, 0, sizeof(description)); - description.numLayers = fCurrNumLayers = 1; + plMetalFragmentShaderDescription description{}; + description.fNumLayers = fCurrNumLayers = 1; description.Populate(proj, 0); // DX sets the color invert when the final color should be inverted. Not sure why! if (proj->GetBlendFlags() & hsGMatState::kBlendInvertFinalColor) { - description.blendModes[0] |= hsGMatState::kBlendInvertColor; + description.fBlendModes[0] |= hsGMatState::kBlendInvertColor; } plMetalMaterialPassPipelineState materialShaderState(&fDevice, vRef, description); @@ -1508,7 +1519,9 @@ bool plMetalPipeline::IHandleMaterialPass(hsGMaterial* material, uint32_t pass, ISetCullMode(); } - // Some build passes don't allow shaders. Render the geometry and the provided material, but don't allow the shader path if instructed to. In the DX source, this would be done by the render phase setting the shaders to null after calling this. That won't work here in since our pipeline state has to know the shaders. + // Some build passes don't allow shaders. Render the geometry and the provided material, but don't allow the + // shader path if instructed to. In the DX source, this would be done by the render phase setting the shaders + // to null after calling this. That won't work here in since our pipeline state has to know the shaders. if (lay->GetVertexShader() && allowShaders) { lay = IPushOverBaseLayer(lay); lay = IPushOverAllLayer(lay); @@ -1622,32 +1635,39 @@ bool plMetalPipeline::IHandleMaterialPass(hsGMaterial* material, uint32_t pass, fragmentShaderDescription = mRef->GetFragmentShaderDescription(pass); } else { // Plasma pulls piggybacks from the rear first, pull the number of active piggybacks - auto firstPiggyback = fPiggyBackStack.end() - numActivePiggyBacks; - auto lastPiggyback = fPiggyBackStack.end(); + auto firstPiggyback = fPiggyBackStack.end() - numActivePiggyBacks; + auto lastPiggyback = fPiggyBackStack.end(); + std::vector subPiggybacks(firstPiggyback, lastPiggyback); - mRef->EncodeArguments( - fDevice.CurrentRenderCommandEncoder(), fCurrentRenderPassUniforms, pass, &fragmentShaderDescription, &subPiggybacks, - [&](plLayerInterface* layer, uint32_t index) { + + auto preEncodeTransform = [this](plLayerInterface* layer, uint32_t index) { if (index == 0) { layer = IPushOverBaseLayer(layer); } layer = IPushOverAllLayer(layer); - + return layer; - }, - [&](plLayerInterface* layer, uint32_t index) { + }; + + auto postEncodeTransform = [this](plLayerInterface* layer, uint32_t index) { layer = IPopOverAllLayer(layer); if (index == 0) layer = IPopOverBaseLayer(layer); return layer; - }); + }; + + mRef->EncodeArguments(fDevice.CurrentRenderCommandEncoder(), + fCurrentRenderPassUniforms, + pass, + &fragmentShaderDescription, + &subPiggybacks, + preEncodeTransform, + postEncodeTransform); } plMetalDevice::plMetalLinkedPipeline* linkedPipeline = plMetalMaterialPassPipelineState(&fDevice, vRef, fragmentShaderDescription).GetRenderPipelineState(); const MTL::RenderPipelineState* pipelineState = linkedPipeline->pipelineState; - - /*plMetalDevice::plMetalLinkedPipeline *pipeline = fDevice.pipelineStateFor(vRef, s.fBlendFlags, numActivePiggyBacks + mRef->fPassLengths[pass], plShaderID::Unregistered, plShaderID::Unregistered, sources, blendModes, miscFlags); - const MTL::RenderPipelineState *pipelineState = pipeline->pipelineState;*/ + if (fState.fCurrentPipelineState != pipelineState) { fDevice.CurrentRenderCommandEncoder()->setRenderPipelineState(pipelineState); fState.fCurrentPipelineState = pipelineState; @@ -2051,62 +2071,21 @@ void plMetalPipeline::ISetLayer(uint32_t lay) void plMetalPipeline::IHandleBlendMode(hsGMatState flags) { - // No color, just writing out Z values. + // This function is a weird leftover of CPU side blend mode setting. + // We need the error case, but nothing else? In Metal this is all + // done GPU side - but the GPU can't write an error state on a CPU + // side buffer. if (flags.fBlendFlags & hsGMatState::kBlendNoColor) { - // printf("glBlendFunc(GL_ZERO, GL_ONE);\n"); flags.fBlendFlags |= 0x80000000; } else { switch (flags.fBlendFlags & hsGMatState::kBlendMask) { - // Detail is just a special case of alpha, handled in construction of the texture - // mip chain by making higher levels of the chain more transparent. case hsGMatState::kBlendDetail: case hsGMatState::kBlendAlpha: - if (flags.fBlendFlags & hsGMatState::kBlendInvertFinalAlpha) { - if (flags.fBlendFlags & hsGMatState::kBlendAlphaPremultiplied) { - // printf("glBlendFunc(GL_ONE, GL_SRC_ALPHA);\n"); - } else { - // printf("glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);\n"); - } - } else { - if (flags.fBlendFlags & hsGMatState::kBlendAlphaPremultiplied) { - // printf("glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);\n"); - } else { - // printf("glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n"); - } - } - break; - - // Multiply the final color onto the frame buffer. case hsGMatState::kBlendMult: - if (flags.fBlendFlags & hsGMatState::kBlendInvertFinalColor) { - // printf("glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);\n"); - } else { - // printf("glBlendFunc(GL_ZERO, GL_SRC_COLOR);\n"); - } - break; - - // Add final color to FB. case hsGMatState::kBlendAdd: - // printf("glBlendFunc(GL_ONE, GL_ONE);\n"); - break; - - // Multiply final color by FB color and add it into the FB. case hsGMatState::kBlendMADD: - // printf("glBlendFunc(GL_DST_COLOR, GL_ONE);\n"); - break; - - // Final color times final alpha, added into the FB. case hsGMatState::kBlendAddColorTimesAlpha: - if (flags.fBlendFlags & hsGMatState::kBlendInvertFinalAlpha) { - // printf("glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE);\n"); - } else { - // printf("glBlendFunc(GL_SRC_ALPHA, GL_ONE);\n"); - } - break; - - // Overwrite final color onto FB case 0: - // printf("glBlendFunc(GL_ONE, GL_ZERO);\n"); break; default: { @@ -2121,7 +2100,8 @@ void plMetalPipeline::IHandleBlendMode(hsGMatState flags) } // layer state needs to be syncronized to the GPU static_cast(fCurrMaterial->GetDeviceRef())->SetDirty(true); - } break; + } + break; } } } @@ -2492,7 +2472,7 @@ void plMetalPipeline::IDrawPlate(plPlate* plate) fDevice.CurrentRenderCommandEncoder()->setDepthStencilState(pm->fDepthState); fDevice.CurrentRenderCommandEncoder()->setCullMode(MTL::CullModeNone); - int uniformSize = sizeof(VertexUniforms); + int uniformSize = sizeof(VertexUniforms); VertexUniforms uniforms; uniforms.projectionMatrix = projMat; matrix_float4x4 modelMatrix; @@ -2991,36 +2971,38 @@ void plMetalPipeline::IReleaseRenderTargetPools() for (i = 0; i < fRenderTargetPool512.size(); i++) { delete fRenderTargetPool512[i]; - fRenderTargetPool512[i] = nil; + fRenderTargetPool512[i] = nullptr; } fRenderTargetPool512.clear(); for (i = 0; i < fRenderTargetPool256.size(); i++) { delete fRenderTargetPool256[i]; - fRenderTargetPool256[i] = nil; + fRenderTargetPool256[i] = nullptr; } fRenderTargetPool256.clear(); for (i = 0; i < fRenderTargetPool128.size(); i++) { delete fRenderTargetPool128[i]; - fRenderTargetPool128[i] = nil; + fRenderTargetPool128[i] = nullptr; } fRenderTargetPool128.clear(); for (i = 0; i < fRenderTargetPool64.size(); i++) { delete fRenderTargetPool64[i]; - fRenderTargetPool64[i] = nil; + fRenderTargetPool64[i] = nullptr; } fRenderTargetPool64.clear(); for (i = 0; i < fRenderTargetPool32.size(); i++) { delete fRenderTargetPool32[i]; - fRenderTargetPool32[i] = nil; + fRenderTargetPool32[i] = nullptr; } fRenderTargetPool32.clear(); for (i = 0; i < kMaxRenderTargetNext; i++) { fRenderTargetNext[i] = 0; + // Blur is implemented in Metal through MPS. + // If we need a hand written blur algorithm implement here. // fBlurScratchRTs[i] = nil; // fBlurDestRTs[i] = nil; } @@ -3439,13 +3421,13 @@ hsGDeviceRef* plMetalPipeline::SharedRenderTargetRef(plRenderTarget* share, plRe #endif // HS_DEBUGGING /// Check--is this renderTarget really a child of a cubicRenderTarget? - if (owner->GetParent() != nil) { + if (owner->GetParent() != nullptr) { /// This'll create the deviceRefs for all of its children as well SharedRenderTargetRef(share->GetParent(), owner->GetParent()); return owner->GetDeviceRef(); } - if (owner->GetDeviceRef() != nil) + if (owner->GetDeviceRef() != nullptr) ref = (plMetalRenderTargetRef*)owner->GetDeviceRef(); // Look for a good format of matching color and depth size. @@ -3467,9 +3449,9 @@ hsGDeviceRef* plMetalPipeline::SharedRenderTargetRef(plRenderTarget* share, plRe // Check for Cubic. This is unlikely, since this function is currently only // used for the shadow map pools. cubicRT = plCubicRenderTarget::ConvertNoRef(owner); - if (cubicRT != nil) { + if (cubicRT != nullptr) { /// And create the ref (it'll know how to set all the flags) - if (ref != nil) + if (ref != nullptr) ref->SetOwner(owner); else { ref = new plMetalRenderTargetRef(); @@ -3486,7 +3468,7 @@ hsGDeviceRef* plMetalPipeline::SharedRenderTargetRef(plRenderTarget* share, plRe plRenderTarget* face = cubicRT->GetFace(i); plMetalRenderTargetRef* fRef; - if (face->GetDeviceRef() != nil) { + if (face->GetDeviceRef() != nullptr) { fRef = (plMetalRenderTargetRef*)face->GetDeviceRef(); fRef->SetOwner(face); if (!fRef->IsLinked()) @@ -3504,14 +3486,14 @@ hsGDeviceRef* plMetalPipeline::SharedRenderTargetRef(plRenderTarget* share, plRe ref->fTexture = cubeTexture; } else { hsRefCnt_SafeUnRef(ref); - ref = nil; + ref = nullptr; } } // Is it a texture render target? Probably, since shadow maps are all we use this for. else if (owner->GetFlags() & plRenderTarget::kIsTexture || owner->GetFlags() & plRenderTarget::kIsOffscreen) { // DX seperated the onscreen and offscreen types. Metal doesn't care. All render targets are textures. /// Create a normal texture - if (ref != nil) + if (ref != nullptr) ref->SetOwner(owner); else { ref = new plMetalRenderTargetRef(); @@ -3526,7 +3508,7 @@ hsGDeviceRef* plMetalPipeline::SharedRenderTargetRef(plRenderTarget* share, plRe ref->fTexture = texture; } else { hsRefCnt_SafeUnRef(ref); - ref = nil; + ref = nullptr; } if (owner->GetZDepth() && (owner->GetFlags() & (plRenderTarget::kIsTexture | plRenderTarget::kIsOffscreen))) { @@ -3550,14 +3532,14 @@ hsGDeviceRef* plMetalPipeline::SharedRenderTargetRef(plRenderTarget* share, plRe owner->SetDeviceRef(ref); // Unref now, since for now ONLY the RT owns the ref, not us (not until we use it, at least) hsRefCnt_SafeUnRef(ref); - if (ref != nil && !ref->IsLinked()) + if (ref != nullptr && !ref->IsLinked()) ref->Link(&fRenderTargetRefList); } else { - if (ref != nil && !ref->IsLinked()) + if (ref != nullptr && !ref->IsLinked()) ref->Link(&fRenderTargetRefList); } - if (ref != nil) { + if (ref != nullptr) { ref->SetDirty(false); } @@ -3592,7 +3574,7 @@ void plMetalPipeline::IMakeRenderTargetPools() }; int i; for (i = 0; i < kMaxRenderTargetNext; i++) { - std::vector* pool = nil; + std::vector* pool = nullptr; switch (i) { default: case 0: @@ -3621,7 +3603,7 @@ void plMetalPipeline::IMakeRenderTargetPools() if (pool) { pool->resize(kCount[i] + 1); (*pool)[0] = nil; - (*pool)[(int)(kCount[i])] = nil; + (*pool)[(int)(kCount[i])] = nullptr; int j; for (j = 0; j < kCount[i]; j++) { uint16_t flags = plRenderTarget::kIsTexture | plRenderTarget::kIsProjected; @@ -3675,8 +3657,8 @@ void plMetalPipeline::IResetRenderTargetPools() int i; for (i = 0; i < kMaxRenderTargetNext; i++) { fRenderTargetNext[i] = 0; - // fBlurScratchRTs[i] = nil; - // fBlurDestRTs[i] = nil; + // fBlurScratchRTs[i] = nullptr; + // fBlurDestRTs[i] = nullptr; } // fLights.fNextShadowLight = 0; @@ -3695,7 +3677,7 @@ void plMetalPipeline::IRenderShadowCasterSpan(plShadowSlave* slave, plDrawableSp plMetalVertexBufferRef* vRef = (plMetalVertexBufferRef*)drawable->GetVertexRef(span.fGroupIdx, span.fVBufferIdx); plMetalIndexBufferRef* iRef = (plMetalIndexBufferRef*)drawable->GetIndexRef(span.fGroupIdx, span.fIBufferIdx); - if (vRef->GetBuffer() == nil || iRef->GetBuffer() == nil) { + if (vRef->GetBuffer() == nullptr || iRef->GetBuffer() == nullptr) { hsAssert(false, "Trying to render a nil buffer pair!"); return; } @@ -3767,10 +3749,9 @@ void plMetalPipeline::IRenderShadowsOntoSpan(const plRenderPrimFunc& render, con plShadowState shadowState; ISetupShadowState(fShadows[i], shadowState); - struct plMetalFragmentShaderDescription passDescription; - memset(&passDescription, 0, sizeof(passDescription)); + struct plMetalFragmentShaderDescription passDescription{}; - passDescription.numLayers = fCurrNumLayers = 3; + passDescription.fNumLayers = fCurrNumLayers = 3; /* Things get a wee bit complicated here. @@ -3795,7 +3776,7 @@ void plMetalPipeline::IRenderShadowsOntoSpan(const plRenderPrimFunc& render, con } // There's no texture for the third stage if we're reusing the textures // for the first and second stages from the last render. - passDescription.passTypes[2] = PassTypeColor; + passDescription.fPassTypes[2] = PassTypeColor; plMetalDevice::plMetalLinkedPipeline* linkedPipeline = plMetalRenderShadowPipelineState(&fDevice, vRef, passDescription).GetRenderPipelineState(); if (fState.fCurrentPipelineState != linkedPipeline->pipelineState) { diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipelineState.cpp b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipelineState.cpp index 2f662b7a8c..640599a957 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipelineState.cpp +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipelineState.cpp @@ -79,9 +79,9 @@ void plMetalRenderSpanPipelineState::GetFunctionConstants(MTL::FunctionConstantV size_t plMetalRenderSpanPipelineState::GetHash() const { - std::size_t h1 = std::hash()(fNumUVs); - std::size_t h2 = std::hash()(fNumWeights); - std::size_t h3 = std::hash()(fHasSkinIndices); + size_t h1 = std::hash()(fNumUVs); + size_t h2 = std::hash()(fNumWeights); + size_t h3 = std::hash()(fHasSkinIndices); return h1 ^ h2 ^ h3 ^ plMetalPipelineState::GetHash(); } @@ -106,15 +106,15 @@ plMetalMaterialPassPipelineState::plMetalMaterialPassPipelineState(plMetalDevice void plMetalMaterialPassPipelineState::GetFunctionConstants(MTL::FunctionConstantValues* constants) const { plMetalRenderSpanPipelineState::GetFunctionConstants(constants); - constants->setConstantValue(&fFragmentShaderDescription.numLayers, MTL::DataTypeUChar, FunctionConstantNumLayers); - constants->setConstantValues(&fFragmentShaderDescription.passTypes, MTL::DataTypeUChar, NS::Range(FunctionConstantSources, 8)); - constants->setConstantValues(&fFragmentShaderDescription.blendModes, MTL::DataTypeUInt, NS::Range(FunctionConstantBlendModes, 8)); - constants->setConstantValues(&fFragmentShaderDescription.miscFlags, MTL::DataTypeUInt, NS::Range(FunctionConstantLayerFlags, 8)); + constants->setConstantValue(&fFragmentShaderDescription.fNumLayers, MTL::DataTypeUChar, FunctionConstantNumLayers); + constants->setConstantValues(&fFragmentShaderDescription.fPassTypes, MTL::DataTypeUChar, NS::Range(FunctionConstantSources, 8)); + constants->setConstantValues(&fFragmentShaderDescription.fBlendModes, MTL::DataTypeUInt, NS::Range(FunctionConstantBlendModes, 8)); + constants->setConstantValues(&fFragmentShaderDescription.fMiscFlags, MTL::DataTypeUInt, NS::Range(FunctionConstantLayerFlags, 8)); } size_t plMetalMaterialPassPipelineState::GetHash() const { - std::size_t value = plMetalRenderSpanPipelineState::GetHash(); + size_t value = plMetalRenderSpanPipelineState::GetHash(); value ^= fFragmentShaderDescription.GetHash(); return value; @@ -124,7 +124,7 @@ void plMetalRenderSpanPipelineState::ConfigureVertexDescriptor(MTL::VertexDescri { int vertOffset = 0; int skinWeightOffset = vertOffset + (sizeof(float) * 3); - if (this->fHasSkinIndices) { + if (fHasSkinIndices) { skinWeightOffset += sizeof(uint32_t); } int normOffset = skinWeightOffset + (sizeof(float) * this->fNumWeights); @@ -140,7 +140,7 @@ void plMetalRenderSpanPipelineState::ConfigureVertexDescriptor(MTL::VertexDescri vertexDescriptor->attributes()->object(VertexAttributeNormal)->setBufferIndex(0); vertexDescriptor->attributes()->object(VertexAttributeNormal)->setOffset(normOffset); - if (this->fNumWeights > 0) { + if (fNumWeights > 0) { int weightOneOffset = skinWeightOffset; vertexDescriptor->attributes()->object(VertexAttributeWeights)->setFormat(MTL::VertexFormatFloat); @@ -298,14 +298,14 @@ const NS::String* plMetalMaterialPassPipelineState::GetDescription() void plMetalMaterialPassPipelineState::ConfigureBlend(MTL::RenderPipelineColorAttachmentDescriptor* descriptor) { - uint32_t blendMode = fFragmentShaderDescription.blendModes[0]; + uint32_t blendMode = fFragmentShaderDescription.fBlendModes[0]; ConfigureBlendMode(blendMode, descriptor); } void plMetalFragmentShaderDescription::Populate(const plLayerInterface* layPtr, const uint8_t index) { - blendModes[index] = layPtr->GetBlendFlags(); - miscFlags[index] = layPtr->GetMiscFlags(); + fBlendModes[index] = layPtr->GetBlendFlags(); + fMiscFlags[index] = layPtr->GetMiscFlags(); PopulateTextureInfo(layPtr, index); } @@ -314,15 +314,15 @@ void plMetalFragmentShaderDescription::PopulateTextureInfo(const plLayerInterfac plBitmap* texture = layPtr->GetTexture(); if (texture != nullptr) { if (plCubicEnvironmap::ConvertNoRef(texture) != nullptr || plCubicRenderTarget::ConvertNoRef(texture) != nullptr) { - passTypes[index] = PassTypeCubicTexture; + fPassTypes[index] = PassTypeCubicTexture; } else if (plMipmap::ConvertNoRef(texture) != nullptr || plRenderTarget::ConvertNoRef(texture) != nullptr) { - passTypes[index] = PassTypeTexture; + fPassTypes[index] = PassTypeTexture; } else { - passTypes[index] = PassTypeColor; + fPassTypes[index] = PassTypeColor; } } else { - passTypes[index] = PassTypeColor; + fPassTypes[index] = PassTypeColor; } } diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipelineState.h b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipelineState.h index 00f83516a9..61882871b6 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipelineState.h +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPipelineState.h @@ -50,6 +50,17 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "plMetalDevice.h" #include "plSurface/plShaderTable.h" +enum plMetalPipelineType +{ + // Unknown is for abstract types, don't use it + Unknown = 0, + MaterialShader, + ShadowCaster, + ShadowRender, + Clear, + Dynamic +}; + //MARK: Base pipeline state class plMetalPipelineState @@ -68,7 +79,7 @@ class plMetalPipelineState } virtual size_t GetHash() const; virtual bool IsEqual(const plMetalPipelineState& p) const = 0; - virtual uint16_t GetID() const { return 0; }; + virtual uint16_t GetID() const { return plMetalPipelineType::Unknown; }; virtual plMetalPipelineState* Clone() = 0; // @@ -129,16 +140,16 @@ class plMetalRenderSpanPipelineState : public plMetalPipelineState struct plMetalFragmentShaderDescription { - uint8_t passTypes[8]; - uint32_t blendModes[8]; - uint32_t miscFlags[8]; - uint8_t numLayers; + uint8_t fPassTypes[8]; + uint32_t fBlendModes[8]; + uint32_t fMiscFlags[8]; + uint8_t fNumLayers; size_t hash; bool operator==(const plMetalFragmentShaderDescription& p) const { - bool match = numLayers == p.numLayers && memcmp(passTypes, p.passTypes, sizeof(passTypes)) == 0 && memcmp(blendModes, p.blendModes, sizeof(blendModes)) == 0 && memcmp(miscFlags, p.miscFlags, sizeof(miscFlags)) == 0; + bool match = fNumLayers == p.fNumLayers && memcmp(fPassTypes, p.fPassTypes, sizeof(fPassTypes)) == 0 && memcmp(fBlendModes, p.fBlendModes, sizeof(fBlendModes)) == 0 && memcmp(fMiscFlags, p.fMiscFlags, sizeof(fMiscFlags)) == 0; return match; } @@ -153,19 +164,19 @@ struct plMetalFragmentShaderDescription if (hash) return hash; - std::size_t value = std::hash()(numLayers); - value ^= std::hash()(numLayers); + std::size_t value = std::hash()(fNumLayers); + value ^= std::hash()(fNumLayers); for (int i = 0; i < 8; i++) { - value ^= std::hash()(blendModes[i]); + value ^= std::hash()(fBlendModes[i]); } for (int i = 0; i < 8; i++) { - value ^= std::hash()(miscFlags[i]); + value ^= std::hash()(fMiscFlags[i]); } for (int i = 0; i < 8; i++) { - value ^= std::hash()(passTypes[i]); + value ^= std::hash()(fPassTypes[i]); } return value; @@ -178,7 +189,7 @@ struct plMetalFragmentShaderDescription template <> struct std::hash { - std::size_t operator()(plMetalFragmentShaderDescription const& s) const noexcept + size_t operator()(plMetalFragmentShaderDescription const& s) const noexcept { return s.GetHash(); } @@ -198,7 +209,7 @@ class plMetalMaterialPassPipelineState : public plMetalRenderSpanPipelineState bool IsEqual(const plMetalPipelineState& p) const override; - uint16_t GetID() const override { return 1; }; + uint16_t GetID() const override { return plMetalPipelineType::MaterialShader; }; plMetalPipelineState* Clone() override { @@ -233,7 +244,7 @@ class plMetalRenderShadowCasterPipelineState : public plMetalRenderSpanPipelineS descriptor->setSourceRGBBlendFactor(MTL::BlendFactorOne); descriptor->setDestinationRGBBlendFactor(MTL::BlendFactorSourceAlpha); }; - uint16_t GetID() const override { return 2; }; + uint16_t GetID() const override { return plMetalPipelineType::ShadowCaster; }; plMetalPipelineState* Clone() override { @@ -258,7 +269,7 @@ class plMetalRenderShadowPipelineState : public plMetalMaterialPassPipelineState MTL::Function* GetVertexFunction(MTL::Library* library) override; MTL::Function* GetFragmentFunction(MTL::Library* library) override; void ConfigureBlend(MTL::RenderPipelineColorAttachmentDescriptor* descriptor) override; - uint16_t GetID() const override { return 3; }; + uint16_t GetID() const override { return plMetalPipelineType::ShadowRender; }; plMetalPipelineState* Clone() override { @@ -275,9 +286,11 @@ class plMetalDynamicMaterialPipelineState : public plMetalRenderSpanPipelineStat : plMetalRenderSpanPipelineState(device, vRef), fVertexShaderID(vertexShaderID), fFragmentShaderID(fragmentShaderID), - fBlendMode(blendMode){ - - }; + fBlendMode(blendMode) + { + }; + + uint16_t GetID() const override { return plMetalPipelineType::Dynamic; }; plMetalPipelineState* Clone() override { @@ -351,7 +364,7 @@ class plMetalClearPipelineState : public plMetalPipelineState return clearState->fShouldClearDepth == fShouldClearDepth && fShouldClearColor == clearState->fShouldClearColor; }; - uint16_t GetID() const override { return 4; }; + uint16_t GetID() const override { return plMetalPipelineType::Clear; }; plMetalPipelineState* Clone() override { return new plMetalClearPipelineState(*this); @@ -398,7 +411,7 @@ class plMetalClearPipelineState : public plMetalPipelineState size_t GetHash() const override { - std::size_t value = plMetalPipelineState::GetHash(); + size_t value = plMetalPipelineState::GetHash(); value ^= std::hash()(fShouldClearColor); value ^= std::hash()(fShouldClearDepth); diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPlateManager.cpp b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPlateManager.cpp index 23805c8288..4e927dc8b5 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPlateManager.cpp +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPlateManager.cpp @@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "ShaderTypes.h" #include "plMetalPipeline.h" -plMetalPlateManager::plMetalPlateManager(plMetalPipeline *pipe) +plMetalPlateManager::plMetalPlateManager(plMetalPipeline* pipe) : plPlateManager(pipe), fVtxBuffer(nullptr) { @@ -62,7 +62,7 @@ void plMetalPlateManager::ICreateGeometry() { plMetalPipeline *pipeline = (plMetalPipeline *)fOwner; if (!fVtxBuffer) { - struct plateVertexBuffer vertexBuffer; + plateVertexBuffer vertexBuffer; vertexBuffer.vertices[0].Set(-0.5f, -0.5f); vertexBuffer.uv[0].Set(0.0f, 0.0f); @@ -83,7 +83,7 @@ void plMetalPlateManager::ICreateGeometry() } } -void plMetalPlateManager::EncodeDraw(MTL::RenderCommandEncoder *encoder) +void plMetalPlateManager::EncodeDraw(MTL::RenderCommandEncoder* encoder) { encoder->setVertexBuffer(fVtxBuffer, 0, VertexAttributePosition); encoder->setVertexBuffer(fVtxBuffer, offsetof(plateVertexBuffer, uv), VertexAttributeTexcoord); @@ -99,7 +99,7 @@ void plMetalPlateManager::IReleaseGeometry() } } -void plMetalPlateManager::IDrawToDevice(plPipeline *pipe) +void plMetalPlateManager::IDrawToDevice(plPipeline* pipe) { plMetalPipeline *pipeline = (plMetalPipeline *)pipe; plPlate *plate = nullptr; @@ -116,39 +116,39 @@ plMetalPlateManager::~plMetalPlateManager() IReleaseGeometry(); } -bool plMetalPlatePipelineState::IsEqual(const plMetalPipelineState &p) const +bool plMetalPlatePipelineState::IsEqual(const plMetalPipelineState& p) const { return true; } -plMetalPipelineState *plMetalPlatePipelineState::Clone() +plMetalPipelineState* plMetalPlatePipelineState::Clone() { return new plMetalPlatePipelineState(fDevice); } -const MTL::Function *plMetalPlatePipelineState::GetVertexFunction(MTL::Library *library) +const MTL::Function* plMetalPlatePipelineState::GetVertexFunction(MTL::Library* library) { return library->newFunction(MTLSTR("plateVertexShader")); } -const MTL::Function *plMetalPlatePipelineState::GetFragmentFunction(MTL::Library *library) +const MTL::Function* plMetalPlatePipelineState::GetFragmentFunction(MTL::Library* library) { return library->newFunction(MTLSTR("fragmentShader")); } -const NS::String *plMetalPlatePipelineState::GetDescription() +const NS::String* plMetalPlatePipelineState::GetDescription() { return MTLSTR("Plate Pipeline State"); } -void plMetalPlatePipelineState::ConfigureBlend(MTL::RenderPipelineColorAttachmentDescriptor *descriptor) +void plMetalPlatePipelineState::ConfigureBlend(MTL::RenderPipelineColorAttachmentDescriptor* descriptor) { descriptor->setBlendingEnabled(true); descriptor->setSourceRGBBlendFactor(MTL::BlendFactorSourceAlpha); descriptor->setDestinationRGBBlendFactor(MTL::BlendFactorOneMinusSourceAlpha); } -void plMetalPlatePipelineState::ConfigureVertexDescriptor(MTL::VertexDescriptor *vertexDescriptor) +void plMetalPlatePipelineState::ConfigureVertexDescriptor(MTL::VertexDescriptor* vertexDescriptor) { vertexDescriptor->attributes()->object(0)->setFormat(MTL::VertexFormatFloat2); vertexDescriptor->attributes()->object(0)->setBufferIndex(VertexAttributePosition); @@ -161,6 +161,6 @@ void plMetalPlatePipelineState::ConfigureVertexDescriptor(MTL::VertexDescriptor vertexDescriptor->layouts()->object(1)->setStride(sizeof(float) * 2); } -void plMetalPlatePipelineState::GetFunctionConstants(MTL::FunctionConstantValues *) const +void plMetalPlatePipelineState::GetFunctionConstants(MTL::FunctionConstantValues*) const { } diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPlateManager.h b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPlateManager.h index 60e8cfbc5b..3b824766f9 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPlateManager.h +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalPlateManager.h @@ -61,10 +61,10 @@ class plMetalPlatePipelineState : public plMetalPipelineState plMetalPlatePipelineState(plMetalDevice *device) : plMetalPipelineState(device){}; bool IsEqual(const plMetalPipelineState &p) const override; uint16_t GetID() const override { return 5; }; - plMetalPipelineState *Clone() override; - const MTL::Function *GetVertexFunction(MTL::Library *library) override; - const MTL::Function *GetFragmentFunction(MTL::Library *library) override; - const NS::String *GetDescription() override; + plMetalPipelineState* Clone() override; + const MTL::Function * GetVertexFunction(MTL::Library *library) override; + const MTL::Function * GetFragmentFunction(MTL::Library *library) override; + const NS::String* GetDescription() override; void ConfigureBlend(MTL::RenderPipelineColorAttachmentDescriptor *descriptor) override; @@ -78,11 +78,11 @@ class plMetalPlateManager : public plPlateManager friend class plMetalPipeline; public: - plMetalPlateManager(plMetalPipeline *pipe); - void IDrawToDevice(plPipeline *pipe) override; + plMetalPlateManager(plMetalPipeline* pipe); + void IDrawToDevice(plPipeline* pipe) override; void ICreateGeometry(); void IReleaseGeometry(); - void EncodeDraw(MTL::RenderCommandEncoder *encoder); + void EncodeDraw(MTL::RenderCommandEncoder* encoder); ~plMetalPlateManager(); private: @@ -91,9 +91,9 @@ class plMetalPlateManager : public plPlateManager hsPoint2 vertices[4]; hsPoint2 uv[4]; }; - MTL::Buffer *fVtxBuffer; - MTL::Buffer *idxBuffer; - MTL::DepthStencilState *fDepthState; + MTL::Buffer* fVtxBuffer; + MTL::Buffer* idxBuffer; + MTL::DepthStencilState* fDepthState; }; #endif /* plMetalPlateManager_hpp */ diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalShader.cpp b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalShader.cpp index 3e0b225e01..a82c6f03e3 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalShader.cpp +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalShader.cpp @@ -47,16 +47,14 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com plMetalShader::plMetalShader(plShader* owner) : fOwner(owner), - fPipe(nil) + fPipe() { owner->SetDeviceRef(this); } plMetalShader::~plMetalShader() { - fPipe = nil; - - // ISetError(nil); + fPipe = nullptr; } void plMetalShader::SetOwner(plShader* owner) @@ -67,14 +65,3 @@ void plMetalShader::SetOwner(plShader* owner) owner->SetDeviceRef(this); } } - -/*HRESULT plMetalShader::IOnError(HRESULT hr, const char* errStr) -{ - ISetError(errStr); - - fOwner->Invalidate(); - - hsStatusMessage(errStr); - - return hr; -}*/ diff --git a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalShader.h b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalShader.h index 8c5c6a1952..157ae6ce28 100644 --- a/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalShader.h +++ b/Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalShader.h @@ -55,23 +55,17 @@ class plMetalShader : public plMetalDeviceRef { protected: plShader* fOwner; - // ST::string fErrorString; plMetalPipeline* fPipe; MTL::Function* fFunction; - - // HRESULT IOnError(HRESULT hr, const char* errStr); - // void ISetError(const char* errStr) { fErrorString = errStr; } - - // virtual HRESULT ICreate(plDXPipeline* pipe) = 0; + virtual bool ISetConstants(plMetalPipeline* pipe) = 0; // On error, sets error string. public: plMetalShader(plShader* owner); virtual ~plMetalShader(); - // ST::string GetErrorString() const { return fErrorString; } void SetOwner(plShader* owner); - MTL::Function* GetShader(plMetalPipeline* pipe) { return fFunction; }; + MTL::Function* GetShader(plMetalPipeline* pipe) const { return fFunction; }; }; #endif // plDXShader_inc