Skip to content

Commit

Permalink
feat: add visionOS examples
Browse files Browse the repository at this point in the history
  • Loading branch information
okwasniewski committed Aug 12, 2024
1 parent 3f3d3b4 commit a287cae
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 2 deletions.
34 changes: 34 additions & 0 deletions examples/common/entry/entry_visionos.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import SwiftUI
import CompositorServices

// Default configuration
struct ContentStageConfiguration: CompositorLayerConfiguration {
func makeConfiguration(capabilities: LayerRenderer.Capabilities, configuration: inout LayerRenderer.Configuration) {
configuration.depthFormat = .depth32Float
configuration.colorFormat = .bgra8Unorm_srgb

let foveationEnabled = capabilities.supportsFoveation
configuration.isFoveationEnabled = foveationEnabled

let options: LayerRenderer.Capabilities.SupportedLayoutsOptions = foveationEnabled ? [.foveationEnabled] : []
let supportedLayouts = capabilities.supportedLayouts(options: options)

configuration.layout = supportedLayouts.contains(.layered) ? .layered : .dedicated
}
}

@main
struct ExampleApp: App {
var body: some Scene {
ImmersiveSpace {
CompositorLayer(configuration: ContentStageConfiguration()) { layerRenderer in
let renderThread = Thread {
var engine = BgfxAdapter(layerRenderer)
engine.renderLoop()
}
renderThread.name = "Render Thread"
renderThread.start()
}
}
}
}
218 changes: 218 additions & 0 deletions examples/common/entry/swift_adapter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
#include "entry_p.h"

#if ENTRY_CONFIG_USE_NATIVE && BX_PLATFORM_VISIONOS

#include "swift_adapter.h"

#include <bgfx/platform.h>
#include <bx/uint32_t.h>
#include <bx/thread.h>

namespace entry
{
struct MainThreadEntry
{
int m_argc;
const char* const* m_argv;

static int32_t threadFunc(bx::Thread* _thread, void* _userData);
};

static WindowHandle s_defaultWindow = { 0 };

struct Context
{
Context(uint32_t _width, uint32_t _height)
{
static const char* const argv[] = { "visionos" };
m_mte.m_argc = BX_COUNTOF(argv);
m_mte.m_argv = argv;

m_eventQueue.postSizeEvent(s_defaultWindow, _width, _height);


// Prevent render thread creation.
bgfx::renderFrame();

m_thread.init(MainThreadEntry::threadFunc, &m_mte);
}


~Context()
{
m_thread.shutdown();
}

MainThreadEntry m_mte;
bx::Thread m_thread;
void* m_window;

EventQueue m_eventQueue;
};

static Context* s_ctx;

int32_t MainThreadEntry::threadFunc(bx::Thread* _thread, void* _userData)
{
BX_UNUSED(_thread);

if (_thread != NULL) {
_thread->setThreadName("Main Thread BGFX");
}

CFBundleRef mainBundle = CFBundleGetMainBundle();
if (mainBundle != nil)
{
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
if (resourcesURL != nil)
{
char path[PATH_MAX];
if (CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8*)path, PATH_MAX) )
{
chdir(path);
}

CFRelease(resourcesURL);
}
}

MainThreadEntry* self = (MainThreadEntry*)_userData;
int32_t result = main(self->m_argc, self->m_argv);
return result;
}

const Event* poll()
{
return s_ctx->m_eventQueue.poll();
}

const Event* poll(WindowHandle _handle)
{
return s_ctx->m_eventQueue.poll(_handle);
}

void release(const Event* _event)
{
s_ctx->m_eventQueue.release(_event);
}

WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title)
{
BX_UNUSED(_x, _y, _width, _height, _flags, _title);
WindowHandle handle = { UINT16_MAX };
return handle;
}

void destroyWindow(WindowHandle _handle)
{
BX_UNUSED(_handle);
}

void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y)
{
BX_UNUSED(_handle, _x, _y);
}

void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height)
{
BX_UNUSED(_handle, _width, _height);
}

void setWindowTitle(WindowHandle _handle, const char* _title)
{
BX_UNUSED(_handle, _title);
}

void setWindowFlags(WindowHandle _handle, uint32_t _flags, bool _enabled)
{
BX_UNUSED(_handle, _flags, _enabled);
}

void toggleFullscreen(WindowHandle _handle)
{
BX_UNUSED(_handle);
}

void setMouseLock(WindowHandle _handle, bool _lock)
{
BX_UNUSED(_handle, _lock);
}

void* getNativeWindowHandle(WindowHandle _handle)
{
if (kDefaultWindowHandle.idx == _handle.idx)
{
return s_ctx->m_window;
}

return NULL;
}

void* getNativeDisplayHandle()
{
return NULL;
}

bgfx::NativeWindowHandleType::Enum getNativeWindowHandleType()
{
return bgfx::NativeWindowHandleType::Default;
}

} // namespace entry

using namespace entry;

bool BgfxAdapter::initialize(void) {
if (!m_initialized) {
// Set context width and height to default visionOS resolution. It's different for the headset and device.
#if TARGET_OS_SIMULATOR
s_ctx = new Context(2732, 2048);
#else
s_ctx = new Context(1920, 1824);
#endif
s_ctx->m_window = m_layerRenderer;
m_initialized = true;
}

return m_initialized;
}

void BgfxAdapter::shutdown(void) {
if (m_initialized) {
s_ctx->m_eventQueue.postExitEvent();
s_ctx = NULL;
}

m_initialized = false;
}

void BgfxAdapter::render() {
if (!m_initialized) {
return;
}
bgfx::renderFrame();
}

void BgfxAdapter::renderLoop() {
bool isRendering = true;
while (isRendering) {
switch (cp_layer_renderer_get_state(m_layerRenderer)) {
case cp_layer_renderer_state_paused:
cp_layer_renderer_wait_until_running(m_layerRenderer);
break;

case cp_layer_renderer_state_running:
this->initialize();
this->render();
break;

case cp_layer_renderer_state_invalidated:
isRendering = false;
break;
}
}

this->shutdown();
}

#endif // BX_PLATFORM_VISIONOS
25 changes: 25 additions & 0 deletions examples/common/entry/swift_adapter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef SWIFT_ADAPTER_H_HEADER_GUARD
#define SWIFT_ADAPTER_H_HEADER_GUARD

#include <CompositorServices/CompositorServices.h>

class BgfxAdapter {
private:
bool m_initialized = false;
cp_layer_renderer_t m_layerRenderer = NULL;
void render(void);

public:
BgfxAdapter(cp_layer_renderer_t layerRenderer) : m_layerRenderer(layerRenderer) {
}

~BgfxAdapter() {
shutdown();
}

bool initialize(void);
void shutdown(void);
void renderLoop(void);
};

#endif
33 changes: 33 additions & 0 deletions examples/runtime/xros-info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Examples Debug</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationPreferredDefaultSceneSessionRole</key>
<string>CPSceneSessionRoleImmersiveSpaceApplication</string>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
</dict>
</dict>
</plist>
12 changes: 12 additions & 0 deletions scripts/example-common.lua
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ project ("example-common")
path.join(BGFX_DIR, "examples/common/**.mm"),
}

configuration { "xros*" }
files {
path.join(BGFX_DIR, "examples/common/**.swift"),
path.join(BGFX_DIR, "examples/common/**.hpp"),
path.join(BGFX_DIR, "examples/common/**.modulemap"),
}
xcodeprojectopts {
SWIFT_VERSION = "5.0",
SWIFT_OBJC_BRIDGING_HEADER = path.join(BGFX_DIR, "examples/common/entry/swift_adapter.h"),
SWIFT_OBJC_INTEROP_MODE = "objcxx",
}

configuration { "winstore* or durango"}
files {
path.join(BGFX_DIR, "examples/common/**.cx"),
Expand Down
15 changes: 13 additions & 2 deletions scripts/genie.lua
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,8 @@ function exampleProjectDefaults()
"-weak_framework Metal",
}

configuration { "ios* or tvos*" }
kind "ConsoleApp"
configuration { "ios* or tvos* or xros*" }
kind "WindowedApp"
linkoptions {
"-framework CoreFoundation",
"-framework Foundation",
Expand All @@ -419,6 +419,11 @@ function exampleProjectDefaults()
"-framework UIKit",
"-weak_framework Metal",
}
xcodecopyresources {
{ "shaders/metal", {
os.matchfiles(path.join(BGFX_DIR, "examples/runtime/shaders/metal/**.bin"))
}}
}

configuration { "xcode*", "ios" }
kind "WindowedApp"
Expand All @@ -432,6 +437,12 @@ function exampleProjectDefaults()
path.join(BGFX_DIR, "examples/runtime/tvOS-Info.plist"),
}

configuration { "xcode*", "xros" }
kind "WindowedApp"
files {
path.join(BGFX_DIR, "examples/runtime/xros-info.plist"),
}

configuration {}

strip()
Expand Down

0 comments on commit a287cae

Please sign in to comment.