Skip to content

Commit

Permalink
[Mac] Made Mac apps launchable without command line terminal.
Browse files Browse the repository at this point in the history
- Examples on macOS can finally be launched by double clicking the .app packages from Finder.
- Added same NSBundle resource file loading as for iOS.
- Removed old command buffer encoding with two queue submissions from ClothPhysics example (Originally added to fix issue with Metal backend).
- Fixed loading compute shaders and ShaderErrors test for Mac.
  • Loading branch information
LukasBanana committed Jun 5, 2024
1 parent e774985 commit 68265ce
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 66 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ function(add_project_resource_files OUTPUT_LIST)
set(ResourceFiles "")
set(InputFilenames "${ARGN}")
foreach(InputFile ${InputFilenames})
if("${InputFile}" MATCHES ".+\\.(png|jpg|dds)")
if("${InputFile}" MATCHES ".+\\.(png|jpg|dds|tga)")
file(GLOB TextureResourceFiles "${EXAMPLE_MEDIA_DIR}/Textures/${InputFile}")
list(APPEND ResourceFiles "${TextureResourceFiles}")
elseif("${InputFile}" MATCHES ".+\\.(obj)")
Expand Down Expand Up @@ -278,7 +278,7 @@ function(add_llgl_example_project PROJECT_NAME LINKER_LANG SRC_FILES LIB_FILES)

# Filter resource files into "Resources" folder
set(RES_FILES "${SRC_FILES}")
list(FILTER RES_FILES INCLUDE REGEX ".+\\.(obj|png|jpg|dds|icns)")
list(FILTER RES_FILES INCLUDE REGEX ".+\\.(obj|png|jpg|dds|tga|icns)")
source_group("Resources" FILES ${RES_FILES})

# Don't compile these resource types, just keep them in the project solution
Expand Down
11 changes: 11 additions & 0 deletions examples/C99/HelloTriangle/HelloTriangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ int main(int argc, char* argv[])
};
LLGLSwapChain swapChain = llglCreateSwapChain(&swapChainDesc);

// Print information about the selected renderer
LLGLRendererInfo info = {};
llglGetRendererInfo(&info);
printf(
"Renderer: %s\n"
"Device: %s\n"
"Vendor: %s\n"
"Shading Language: %s\n",
info.rendererName, info.deviceName, info.vendorName, info.shadingLanguageName
);

// Enable V-sync
llglSetVsyncInterval(swapChain, 1);

Expand Down
48 changes: 36 additions & 12 deletions examples/Cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,21 @@ project(LLGL_ExamplesCpp)
# Example project files
find_source_files(FilesExampleBase CXX "${EXAMPLEBASE_PROJECT_DIR}")

if(LLGL_IOS_PLATFORM)
find_source_files(FilesExampleBaseIOS OBJC "${EXAMPLEBASE_PROJECT_DIR}/iOS")
endif()
if(APPLE)
if(LLGL_IOS_PLATFORM)
find_source_files(FilesExampleBaseIOS OBJC "${EXAMPLEBASE_PROJECT_DIR}/iOS")
else()
find_source_files(FilesExampleBaseMacOS OBJC "${EXAMPLEBASE_PROJECT_DIR}/macOS")
endif()
endif(APPLE)

set(FilesExampleBaseAll ${FilesExampleBase})
if(LLGL_IOS_PLATFORM)
set(FilesExampleBaseAll ${FilesExampleBaseAll} ${FilesExampleBaseIOS})
endif()

if(APPLE)
if(LLGL_IOS_PLATFORM)
set(FilesExampleBaseAll ${FilesExampleBaseAll} ${FilesExampleBaseIOS})
else()
set(FilesExampleBaseAll ${FilesExampleBaseAll} ${FilesExampleBaseMacOS})
endif()
set_source_files_properties("${EXAMPLEBASE_PROJECT_DIR}/ExampleBase.cpp" PROPERTIES COMPILE_FLAGS -xobjective-c++)
endif()

Expand Down Expand Up @@ -52,8 +57,8 @@ find_project_source_files( FilesExample_VolumeRendering "${EXAMPLE_CPP_PROJE

find_project_source_files( FilesExample_HelloUWP "${EXAMPLE_CPP_PROJECTS_DIR}/HelloUWP" )

# Append extra resources for mobile platforms
if(LLGL_IOS_PLATFORM)
# Append extra resources for app bundles (iOS/macOS)
if(APPLE)
add_project_resource_files(FilesExample_Fonts
"FontAtlas_*.png"
)
Expand All @@ -67,6 +72,15 @@ if(LLGL_IOS_PLATFORM)
add_project_resource_files(FilesExample_ClothPhysics
"Logo_LLGL.png"
)
add_project_resource_files(FilesExample_PBR
"UVSphere.obj"
"WiredBox.obj"
"PBR/mp_alpha/alpha-island_*.tga"
"PBR/Metal04/Metal04_*.jpg"
"PBR/Tiles22/Tiles22_*.jpg"
"PBR/Tiles26/Tiles26_*.jpg"
"PBR/Wood13/Wood13_*.jpg"
)
add_project_resource_files(FilesExample_RenderTarget
"Crate.jpg"
)
Expand Down Expand Up @@ -97,16 +111,26 @@ if(LLGL_IOS_PLATFORM)
"Grass.jpg"
"Plants_*.png"
)
if(NOT LLGL_MOBILE_PLATFORM)
add_project_resource_files(FilesExample_MultiRenderer
"Logo_Metal.png"
"Logo_OpenGL.png"
)
endif()
endif()


# === Source group folders ===

source_group("Sources" FILES ${FilesExampleBase})

if(LLGL_IOS_PLATFORM)
source_group("Sources\\iOS" FILES ${FilesExampleBaseIOS})
endif()
if(APPLE)
if(LLGL_IOS_PLATFORM)
source_group("Sources\\iOS" FILES ${FilesExampleBaseIOS})
else()
source_group("Sources\\macOS" FILES ${FilesExampleBaseMacOS})
endif()
endif(APPLE)


# === Include directories ===
Expand Down
6 changes: 0 additions & 6 deletions examples/Cpp/ClothPhysics/Example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,13 +607,7 @@ class Example_ClothPhysics : public ExampleBase
commands->Dispatch(clothSegmentsU + 1, clothSegmentsV + 1, 1);
}
commands->PopDebugGroup();
}
commands->End();
commandQueue->Submit(*commands);

// Record and submit graphics commands
commands->Begin();
{
// Draw scene
commands->BeginRenderPass(*swapChain);
{
Expand Down
38 changes: 17 additions & 21 deletions examples/Cpp/ExampleBase/ExampleBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,23 @@ static void GetSelectedRendererModuleOrDefault(std::string& rendererModule, int
std::cout << "selected renderer: " << rendererModule << std::endl;
}

static constexpr const char* GetDefaultRendererModule()
{
#if defined LLGL_OS_WIN32
return "Direct3D11";
#elif defined LLGL_OS_IOS || defined LLGL_OS_MACOS
return "Metal";
#elif defined LLGL_OS_ANDROID
return "OpenGLES3";
#else
return "OpenGL";
#endif
}

std::string GetSelectedRendererModule(int argc, char* argv[])
{
std::string rendererModule;
if (const char* specificModule = GetRendererModuleFromCommandArgs(argc, argv))
rendererModule = specificModule;
else
rendererModule = GetRendererModuleFromUserSelection(argc, argv);
std::cout << "selected renderer: " << rendererModule << std::endl;
std::string rendererModule = GetDefaultRendererModule();
GetSelectedRendererModuleOrDefault(rendererModule, argc, argv);
return rendererModule;
}

Expand Down Expand Up @@ -289,19 +298,6 @@ void ExampleBase::CanvasEventHandler::OnResize(LLGL::Canvas& /*sender*/, const L
* ExampleBase class
*/

static constexpr const char* GetDefaultRendererModule()
{
#if defined LLGL_OS_WIN32
return "Direct3D11";
#elif defined LLGL_OS_IOS || defined LLGL_OS_MACOS
return "Metal";
#elif defined LLGL_OS_ANDROID
return "OpenGLES3";
#else
return "OpenGL";
#endif
}

struct ExampleConfig
{
std::string rendererModule = GetDefaultRendererModule();
Expand All @@ -319,7 +315,7 @@ android_app* ExampleBase::androidApp_;

void ExampleBase::ParseProgramArgs(int argc, char* argv[])
{
GetSelectedRendererModuleOrDefault(g_Config.rendererModule, argc, argv);
g_Config.rendererModule = GetSelectedRendererModule(argc, argv);
ParseWindowSize(g_Config.windowSize, argc, argv);
ParseSamples(g_Config.samples, argc, argv);
if (HasArgument("-v0", argc, argv) || HasArgument("--novsync", argc, argv))
Expand Down Expand Up @@ -576,7 +572,7 @@ LLGL::Shader* ExampleBase::LoadShaderInternal(
// Forward macro definitions
deviceShaderDesc.defines = defines;

#ifdef LLGL_OS_IOS
#if defined LLGL_OS_IOS || defined LLGL_OS_MACOS
// Always load shaders from default library (default.metallib) when compiling for iOS
deviceShaderDesc.flags |= LLGL::ShaderCompileFlags::DefaultLibrary;
#endif
Expand Down
16 changes: 11 additions & 5 deletions examples/Cpp/ExampleBase/FileUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
#include <fstream>
#include <LLGL/Platform/Platform.h>

#ifdef LLGL_OS_IOS
#if defined LLGL_OS_IOS
# include "iOS/AppUtils.h"
#elif defined LLGL_OS_MACOS
# include "macOS/AppUtils.h"
#endif


Expand All @@ -29,12 +31,16 @@ std::string FindResourcePath(const std::string& filename)
if (FileExists(filename))
return filename;

#ifdef LLGL_OS_IOS
#if defined LLGL_OS_IOS || defined LLGL_OS_MACOS

// Returns filename for resource from main NSBundle
return FindNSResourcePath(filename);
const std::size_t subPathStart = filename.find_last_of('/');
if (subPathStart != std::string::npos)
return FindNSResourcePath(filename.substr(subPathStart + 1));
else
return FindNSResourcePath(filename);

#else // LLGL_OS_IOS
#else

// Search file in resource dependent paths
auto extPos = filename.find_last_of('.');
Expand All @@ -53,7 +59,7 @@ std::string FindResourcePath(const std::string& filename)
return mediaRoot + "Textures/" + filename;
}

#endif // /LLGL_OS_IOS
#endif

return filename;
}
Expand Down
11 changes: 11 additions & 0 deletions examples/Cpp/ExampleBase/macOS/AppUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* AppUtils.h
*
* Copyright (c) 2015 Lukas Hermanns. All rights reserved.
* Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt).
*/

#include <string>

// Tries to find the specified filename in the main NSBundle.
std::string FindNSResourcePath(const std::string& filename);
19 changes: 19 additions & 0 deletions examples/Cpp/ExampleBase/macOS/AppUtils.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* AppUtils.mm
*
* Copyright (c) 2015 Lukas Hermanns. All rights reserved.
* Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt).
*/

#import "AppUtils.h"
#import <Foundation/Foundation.h>


std::string FindNSResourcePath(const std::string& filename)
{
NSString* filenameNS = [[NSString alloc] initWithCString:filename.c_str() encoding:NSASCIIStringEncoding];
NSString* path = [[NSBundle mainBundle] pathForResource:filenameNS ofType:nil];
[filenameNS release];
return (path != nil ? std::string([path UTF8String]) : "");
}

14 changes: 10 additions & 4 deletions examples/Cpp/HelloTriangle/Example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,14 @@ int main(int argc, char* argv[])
swapChain->SetVsyncInterval(1);

// Set window title and show window
auto& window = LLGL::CastTo<LLGL::Window>(swapChain->GetSurface());
LLGL::Window* window = nullptr;

window.SetTitle(L"LLGL Example: Hello Triangle");
window.Show();
if (LLGL::IsInstanceOf<LLGL::Window>(swapChain->GetSurface()))
{
window = LLGL::CastTo<LLGL::Window>(&swapChain->GetSurface());
window->SetTitle(L"LLGL Example: Hello Triangle");
window->Show();
}

// Vertex data structure
struct Vertex
Expand Down Expand Up @@ -172,6 +176,8 @@ int main(int argc, char* argv[])
{
vertShaderDesc = { LLGL::ShaderType::Vertex, "Example.metal", "VS", "1.1" };
fragShaderDesc = { LLGL::ShaderType::Fragment, "Example.metal", "PS", "1.1" };
vertShaderDesc.flags |= LLGL::ShaderCompileFlags::DefaultLibrary;
fragShaderDesc.flags |= LLGL::ShaderCompileFlags::DefaultLibrary;
}

// Specify vertex attributes for vertex shader
Expand Down Expand Up @@ -260,7 +266,7 @@ int main(int argc, char* argv[])
// Enter main loop
const float bgColor[4] = { 0.1f, 0.1f, 0.2f, 1.0f };

while (LLGL::Surface::ProcessEvents() && !window.HasQuit())
while (LLGL::Surface::ProcessEvents() && (window == nullptr || !window->HasQuit()))
{
// Begin recording commands
commands->Begin();
Expand Down
3 changes: 3 additions & 0 deletions examples/Cpp/Instancing/Example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <ExampleBase.h>
#include <stb/stb_image.h>
#include <FileUtils.h>
#include <LLGL/Display.h>


Expand Down Expand Up @@ -220,6 +221,8 @@ class Example_Instancing : public ExampleBase
else
filename = "Grass.jpg";

filename = FindResourcePath(filename);

// Load all images from file (using STBI library, see https://github.com/nothings/stb)
int w = 0, h = 0, c = 0;
unsigned char* imageBuffer = stbi_load(filename.c_str(), &w, &h, &c, 4);
Expand Down
9 changes: 6 additions & 3 deletions tests/Testbed/TestbedContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -896,9 +896,12 @@ bool TestbedContext::LoadShaders()
shaders[VSShadowMap] = LoadShaderFromFile(shaderPath + "ShadowMapping.VShadow.330core.vert", ShaderType::Vertex);
shaders[VSShadowedScene] = LoadShaderFromFile(shaderPath + "ShadowMapping.VScene.330core.vert", ShaderType::Vertex);
shaders[PSShadowedScene] = LoadShaderFromFile(shaderPath + "ShadowMapping.PScene.330core.frag", ShaderType::Fragment);
shaders[VSResourceBinding] = LoadShaderFromFile(shaderPath + "ResourceBinding.450core.vert", ShaderType::Vertex, nullptr, nullptr, nullptr, VertFmtEmpty);
shaders[PSResourceBinding] = LoadShaderFromFile(shaderPath + "ResourceBinding.450core.frag", ShaderType::Fragment);
shaders[CSResourceBinding] = LoadShaderFromFile(shaderPath + "ResourceBinding.450core.comp", ShaderType::Compute);
if (IsShadingLanguageSupported(ShadingLanguage::GLSL_450))
{
shaders[VSResourceBinding] = LoadShaderFromFile(shaderPath + "ResourceBinding.450core.vert", ShaderType::Vertex, nullptr, nullptr, nullptr, VertFmtEmpty);
shaders[PSResourceBinding] = LoadShaderFromFile(shaderPath + "ResourceBinding.450core.frag", ShaderType::Fragment);
shaders[CSResourceBinding] = LoadShaderFromFile(shaderPath + "ResourceBinding.450core.comp", ShaderType::Compute);
}
shaders[VSClear] = LoadShaderFromFile(shaderPath + "ClearScreen.330core.vert", ShaderType::Vertex, nullptr, nullptr, nullptr, VertFmtEmpty);
shaders[PSClear] = LoadShaderFromFile(shaderPath + "ClearScreen.330core.frag", ShaderType::Fragment);
}
Expand Down
31 changes: 18 additions & 13 deletions tests/Testbed/UnitTests/TestShaderErrors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,23 +150,28 @@ DEF_TEST( ShaderErrors )

EvaluatePSO(graphicsPSO, "graphicsPSO");

// Create compute PSO
PipelineLayout* computePSOLayout = renderer->CreatePipelineLayout({});
// Clear resources
renderer->Release(*graphicsPSO);
renderer->Release(*graphicsPSOLayout);

ComputePipelineDescriptor computePSODesc;
if (caps.features.hasComputeShaders)
{
computePSODesc.pipelineLayout = computePSOLayout;
computePSODesc.computeShader = LoadShader("SemanticErrors.CSMain", ShaderType::Compute, true);
}
PipelineState* computePSO = renderer->CreatePipelineState(computePSODesc);
// Create compute PSO
PipelineLayout* computePSOLayout = renderer->CreatePipelineLayout({});

EvaluatePSO(computePSO, "computePSO");
ComputePipelineDescriptor computePSODesc;
{
computePSODesc.pipelineLayout = computePSOLayout;
computePSODesc.computeShader = LoadShader("SemanticErrors.CSMain", ShaderType::Compute, true);
}
PipelineState* computePSO = renderer->CreatePipelineState(computePSODesc);

// Clear resources
renderer->Release(*graphicsPSO);
renderer->Release(*graphicsPSOLayout);
renderer->Release(*computePSO);
renderer->Release(*computePSOLayout);
EvaluatePSO(computePSO, "computePSO");

// Clear resources
renderer->Release(*computePSO);
renderer->Release(*computePSOLayout);
}

return result;
}
Expand Down

0 comments on commit 68265ce

Please sign in to comment.