Skip to content

Commit

Permalink
Merge pull request #1581 from colincornaby/build-metal-shaders-as-lib…
Browse files Browse the repository at this point in the history
…rary

Move shaders into shader library target
  • Loading branch information
colincornaby authored Jun 2, 2024
2 parents 419bd83 + b4196f7 commit 71edac8
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 21 deletions.
14 changes: 9 additions & 5 deletions Sources/Plasma/Apps/plClient/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ elseif(APPLE)
Mac-Cocoa/PLSLoginWindowController.xib
Mac-Cocoa/PLSPatcherWindowController.xib
)
list(APPEND plClient_SHADERTARGETS
pfMetalPipelineShadersMSL21
pfMetalPipelineShadersMSL23
)
else()
list(APPEND plClient_SOURCES
main.cpp
Expand Down Expand Up @@ -146,18 +150,15 @@ if(APPLE)
MACOSX_BUNDLE_SHORT_VERSION_STRING "0.1"
RESOURCE "${plClient_XCODE_RESOURCES}"
XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME AppIcon
XCODE_ATTRIBUTE_MTL_FAST_MATH "YES"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=Debug] "INCLUDE_SOURCE"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=RelWithDebInfo] "INCLUDE_SOURCE"
XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Debug] "YES"
XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=RelWithDebInfo] "YES"
XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "${Plasma_SOURCE_DIR}/Sources/Plasma/NucleusLib/inc/"
XCODE_ATTRIBUTE_INSTALL_PATH "/Applications"
XCODE_ATTRIBUTE_SKIP_INSTALL "NO"
XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/Mac-Cocoa/plClient.entitlements"
XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME "YES"
XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER org.Huru.UruExplorer
XCODE_EMBED_RESOURCES "${plClient_SHADERTARGETS}"
)
target_compile_options(plClient PRIVATE -fobjc-arc)
target_sources(plClient PRIVATE Mac-Cocoa/Assets.xcassets)
Expand All @@ -168,6 +169,10 @@ if(APPLE)
TARGETS plClient
DESTINATION client
)

if(${CMAKE_VERSION} VERSION_LESS 3.28)
message(FATAL_ERROR "Cannot build Mac client without CMake 3.28")
endif()

if(PLASMA_APPLE_DEVELOPMENT_TEAM_ID)
set_target_properties(plClient PROPERTIES
Expand Down Expand Up @@ -238,7 +243,6 @@ target_link_libraries(
$<$<BOOL:${PLASMA_PIPELINE_DX}>:pfDXPipeline>
$<$<BOOL:${PLASMA_PIPELINE_GL}>:pfGLPipeline>
$<$<BOOL:${PLASMA_PIPELINE_METAL}>:pfMetalPipeline>
$<$<BOOL:${PLASMA_PIPELINE_METAL}>:pfMetalPipelineShaders>
CURL::libcurl
"$<$<PLATFORM_ID:Darwin>:-framework Cocoa>"
"$<$<PLATFORM_ID:Darwin>:-framework QuartzCore>"
Expand Down
40 changes: 35 additions & 5 deletions Sources/Plasma/FeatureLib/pfMetalPipeline/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ set(pfMetalPipeline_SOURCES
plMetalVertexShader.cpp
plMetalTextFont.cpp
plMetalDevicePerformanceShaders.mm
plMetalDeviceLibraryLoader.mm
)

set(pfMetalPipeline_HEADERS
Expand Down Expand Up @@ -56,14 +57,23 @@ target_link_libraries(pfMetalPipeline
INTERFACE
pnFactory
)
add_dependencies(
pfMetalPipeline
pfMetalPipelineShadersMSL21
pfMetalPipelineShadersMSL23
)

target_include_directories(pfMetalPipeline PUBLIC ${metalcpp_SOURCE_DIR})
target_include_directories(pfMetalPipeline PUBLIC "ShaderSrc")

source_group("Source Files" FILES ${pfMetalPipeline_SOURCES})
source_group("Header Files" FILES ${pfMetalPipeline_HEADERS})

add_library(pfMetalPipelineShaders INTERFACE)
# All supported Macs for Plasma/Metal support MSL 2.1
add_library(pfMetalPipelineShadersMSL21 MODULE)
# Build a 2.3 varient for macOS 11 and/or Apple Silicon specific features
add_library(pfMetalPipelineShadersMSL23 MODULE)

set(pfMetalPipeline_SHADERS
ShaderSrc/FixedPipelineShaders.metal
ShaderSrc/PlateShaders.metal
Expand All @@ -79,8 +89,28 @@ set(pfMetalPipeline_SHADERS
ShaderSrc/GammaCorrection.metal
ShaderSrc/TextFontShader.metal
)
set_source_files_properties(${pfMetalPipeline_SHADERS} TARGET_DIRECTORY plClient PROPERTIES LANGUAGE METAL)
# source group does not work with an interface library in Xcode, but maybe someday...
source_group("Metal Shaders" FILES ${pfMetalPipeline_SHADERS})
set_target_properties(pfMetalPipelineShadersMSL21 PROPERTIES
XCODE_PRODUCT_TYPE com.apple.product-type.metal-library
XCODE_ATTRIBUTE_MTL_LANGUAGE_REVISION Metal21
XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "${Plasma_SOURCE_DIR}/Sources/Plasma/NucleusLib/inc/"
SUFFIX ".metallib"
PREFIX ""
XCODE_ATTRIBUTE_MTL_FAST_MATH "YES"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=Debug] "INCLUDE_SOURCE"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=RelWithDebInfo] "INCLUDE_SOURCE"
)
set_target_properties(pfMetalPipelineShadersMSL23 PROPERTIES
XCODE_PRODUCT_TYPE com.apple.product-type.metal-library
XCODE_ATTRIBUTE_MTL_LANGUAGE_REVISION Metal23
XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "${Plasma_SOURCE_DIR}/Sources/Plasma/NucleusLib/inc/"
SUFFIX ".metallib"
PREFIX ""
XCODE_ATTRIBUTE_MTL_FAST_MATH "YES"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=Debug] "INCLUDE_SOURCE"
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=RelWithDebInfo] "INCLUDE_SOURCE"
)
set_source_files_properties(${pfMetalPipeline_SHADERS} TARGET_DIRECTORY pfMetalPipelineShadersMSL21 PROPERTIES LANGUAGE METAL)
set_source_files_properties(${pfMetalPipeline_SHADERS} TARGET_DIRECTORY pfMetalPipelineShadersMSL23 PROPERTIES LANGUAGE METAL)

target_sources(pfMetalPipelineShaders INTERFACE ${pfMetalPipeline_SHADERS})
target_sources(pfMetalPipelineShadersMSL21 PRIVATE ${pfMetalPipeline_SHADERS})
target_sources(pfMetalPipelineShadersMSL23 PRIVATE ${pfMetalPipeline_SHADERS})
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,17 @@ fragment half4 gammaCorrectFragment(GammaVertexOut in [[stage_in]]
1.0
};
}

#if defined(__METAL_IOS__) || __METAL_VERSION__ >= 230
fragment half4 gammaCorrectFragmentInPlace(GammaVertexOut in [[stage_in]],
half4 color [[color(0)]],
texture1d_array<ushort> LUT [[texture(1)]])
{
return {
half(float(LUT.sample(lutSampler, color.r, 0).x) / USHRT_MAX),
half(float(LUT.sample(lutSampler, color.g, 1).x) / USHRT_MAX),
half(float(LUT.sample(lutSampler, color.b, 2).x) / USHRT_MAX),
1.0
};
}
#endif
16 changes: 6 additions & 10 deletions Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,8 @@ plMetalDevice::plMetalDevice()
fReverseZStencilState = fMetalDevice->newDepthStencilState(depthDescriptor);

depthDescriptor->release();

LoadLibrary();
}

void plMetalDevice::SetViewport()
Expand Down Expand Up @@ -1065,15 +1067,13 @@ void plMetalDevice::StartPipelineBuild(plMetalPipelineRecord& record, std::condi
return;
}

MTL::Library* library = fMetalDevice->newDefaultLibrary();

std::shared_ptr<plMetalPipelineState> pipelineState = record.state;

MTL::RenderPipelineDescriptor* descriptor = MTL::RenderPipelineDescriptor::alloc()->init();
descriptor->setLabel(pipelineState->GetDescription());

const MTL::Function* vertexFunction = pipelineState->GetVertexFunction(library);
const MTL::Function* fragmentFunction = pipelineState->GetFragmentFunction(library);
const MTL::Function* vertexFunction = pipelineState->GetVertexFunction(fShaderLibrary);
const MTL::Function* fragmentFunction = pipelineState->GetFragmentFunction(fShaderLibrary);
descriptor->setVertexFunction(vertexFunction);
descriptor->setFragmentFunction(fragmentFunction);

Expand Down Expand Up @@ -1108,7 +1108,6 @@ void plMetalDevice::StartPipelineBuild(plMetalPipelineRecord& record, std::condi
});

descriptor->release();
library->release();
}

plMetalDevice::plMetalLinkedPipeline* plMetalDevice::PipelineState(plMetalPipelineState* pipelineState)
Expand Down Expand Up @@ -1241,12 +1240,9 @@ MTL::SamplerState* plMetalDevice::SampleStateForClampFlags(hsGMatState::hsGMatCl
void plMetalDevice::CreateGammaAdjustState()
{
MTL::RenderPipelineDescriptor* gammaDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
MTL::Library* library = fMetalDevice->newDefaultLibrary();

gammaDescriptor->setVertexFunction(library->newFunction(MTLSTR("gammaCorrectVertex"))->autorelease());
gammaDescriptor->setFragmentFunction(library->newFunction(MTLSTR("gammaCorrectFragment"))->autorelease());

library->release();
gammaDescriptor->setVertexFunction(fShaderLibrary->newFunction(MTLSTR("gammaCorrectVertex"))->autorelease());
gammaDescriptor->setFragmentFunction(fShaderLibrary->newFunction(MTLSTR("gammaCorrectFragment"))->autorelease());

gammaDescriptor->colorAttachments()->object(0)->setPixelFormat(fFramebufferFormat);

Expand Down
6 changes: 6 additions & 0 deletions Sources/Plasma/FeatureLib/pfMetalPipeline/plMetalDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ class plMetalDevice
void EncodeBlur(MTL::CommandBuffer* commandBuffer, MTL::Texture* texture, float sigma);

MTL::PixelFormat GetFramebufferFormat() const { return fFramebufferFormat; };

MTL::Library* GetShaderLibrary() const { return fShaderLibrary; }

private:
struct plMetalPipelineRecord
Expand Down Expand Up @@ -252,6 +254,10 @@ class plMetalDevice

MTL::CommandBuffer* fBlitCommandBuffer;
MTL::BlitCommandEncoder* fBlitCommandEncoder;

MTL::Library* fShaderLibrary;

void LoadLibrary();

bool NeedsPostprocessing() const
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/

#include <Foundation/Foundation.h>
#include <Metal/Metal.h>
#include "plMetalDevice.h"

void plMetalDevice::LoadLibrary()
{
/*
On iOS we're fine loading the Metal 2.1 library. Metal 2.1 includes
all the Apple Silicon features on iOS. We need Metal 2.3 to get those
features on macOS.
*/

NS::Error* error;

#ifdef TARGET_OS_OSX
if (@available(macOS 11, *)) {
NSURL* shaderURL = [NSBundle.mainBundle URLForResource:@"pfMetalPipelineShadersMSL23" withExtension:@"metallib"];
fShaderLibrary = fMetalDevice->newLibrary(static_cast<NS::URL*>(shaderURL), &error);
} else
#endif
{
NSURL* shaderURL = [NSBundle.mainBundle URLForResource:@"pfMetalPipelineShadersMSL21" withExtension:@"metallib"];
fShaderLibrary = fMetalDevice->newLibrary(static_cast<NS::URL*>(shaderURL), &error);
}
hsAssert(error == nil, "Unexpected error loading Metal shader library");
}
Original file line number Diff line number Diff line change
Expand Up @@ -2744,7 +2744,7 @@ void plMetalPipeline::IPreprocessAvatarTextures()
// But that hash map assumes that it follows the vertex arrangement of the models.
// After a refactor, this function creation should go there.
MTL::RenderPipelineDescriptor* descriptor = MTL::RenderPipelineDescriptor::alloc()->init()->autorelease();
MTL::Library* library = fDevice.fMetalDevice->newDefaultLibrary()->autorelease();
MTL::Library* library = fDevice.GetShaderLibrary();

MTL::Function* vertFunction = library->newFunction(MTLSTR("PreprocessAvatarVertexShader"))->autorelease();
MTL::Function* fragFunction = library->newFunction(MTLSTR("PreprocessAvatarFragmentShader"))->autorelease();
Expand Down

0 comments on commit 71edac8

Please sign in to comment.