Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmake/HalleyProject.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ endif ()

if (APPLE)
set(USE_AVFOUNDATION 1)
set(USE_METAL 0)
set(USE_METAL 1)
set(USE_OPENGL 0)
set(USE_ASIO 1)
endif ()

Expand Down
49 changes: 49 additions & 0 deletions scripts/build_editor_osx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/bin/sh -e

root=$(pwd)
arch=$(uname -m)
script=$(realpath "$0")
script_path=$(dirname "$script")

mkdir -p build

mkdir -p ${script_path}/../bin
cp ${script_path}/../deps/osx/${arch}/lib/libShaderConductor.dylib libShaderConductor.dylib

#
# generate cmake project
#
cd ${root}/build
rm -f CMakeCache.txt

cmake -G "Xcode" \
-DHALLEY_PATH="../halley" \
-DBUILD_HALLEY_TOOLS=1 \
-DBUILD_HALLEY_TESTS=0 \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DHALLEY_ENABLE_STATIC_STDLIB=1 \
-DCMAKE_INCLUDE_PATH="${script_path}/../deps/osx/${arch}/include" \
-DCMAKE_LIBRARY_PATH="${script_path}/../deps/osx/${arch}/lib" \
-DSDL2_INCLUDE_DIR="${script_path}/../deps/osx/${arch}/include/SDL2" \
-DSDL2_LIBRARIES="${script_path}/../deps/osx/${arch}/libSDL2.a" \
-DShaderConductor_INCLUDE_DIR="${script_path}/../deps/osx/${arch}/include/ShaderConductor" \
-DShaderConductor_LIBRARY="${script_path}/../deps/osx/${arch}/lib/libShaderConductor.dylib" \
-DBoost_INCLUDE_DIR="${script_path}/../deps/Boost/include/boost-1_81" \
-DBoost_USE_STATIC_LIBS=1 \
..
#
# compile halley-cmd
#
cmake --build . --target halley-cmd --config RelWithDebInfo -j 4

#
# import assets & code gen
#
cd ${script_path}/../bin
./halley-cmd import ${root} ${root}/halley/

#
# compile halley-editor
#
cd ${root}/build
cmake --build . --target halley-editor --config RelWithDebInfo -j 4
8 changes: 7 additions & 1 deletion src/plugins/metal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
project (halley-metal)

include_directories(${Boost_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} "../../engine/utils/include" "../../engine/core/include")
include_directories(${Boost_INCLUDE_DIR} ${SDL2_INCLUDE_DIR} "../../engine/utils/include" "../../engine/core/include")

set(SOURCES
"src/metal_plugin.mm"
Expand All @@ -13,6 +13,7 @@ set(SOURCES
"src/metal_shader.mm"
"src/metal_texture.mm"
"src/metal_video.mm"
"src/metal_depth_stencil.mm"
)

set(HEADERS
Expand All @@ -24,6 +25,7 @@ set(HEADERS
"src/metal_shader.h"
"src/metal_texture.h"
"src/metal_video.h"
"src/metal_depth_stencil.h"
)

assign_source_group(${SOURCES})
Expand All @@ -36,3 +38,7 @@ set_target_properties(halley-metal PROPERTIES DISABLE_PRECOMPILE_HEADERS ON)
find_library(METAL_LIBRARY Metal)
find_library(QUARTZ_LIBRARY QuartzCore)
target_link_libraries(halley-metal halley-engine "${METAL_LIBRARY}" "${QUARTZ_LIBRARY}")

if(IOS)
target_link_libraries( halley-metal "${SDL2_LIBRARIES}" )
endif()
6 changes: 3 additions & 3 deletions src/plugins/metal/src/metal_buffer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
{}

MetalBuffer::~MetalBuffer() {
[buffer setPurgeableState:MTLPurgeableStateEmpty];
[buffer release];
video.addBufferToRelease( buffer );
buffer = nil;
}

void MetalBuffer::setData(gsl::span<const gsl::byte> data) {
auto oldBuffer = std::move(buffer);
auto oldBuffer = buffer;
buffer = [video.getDevice() newBufferWithBytes:data.data() length:data.size_bytes() options:MTLResourceStorageModeShared];
[oldBuffer setPurgeableState:MTLPurgeableStateEmpty];
[oldBuffer release];
Expand Down
27 changes: 27 additions & 0 deletions src/plugins/metal/src/metal_depth_stencil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once
#include <Metal/Metal.h>
#undef min
#undef max
#include "halley/graphics/material/material_definition.h"

namespace Halley
{
class MaterialDepthStencil;
class MetalVideo;

class MetalDepthStencil
{
public:
MetalDepthStencil(MetalVideo& video, const MaterialDepthStencil& definition);
~MetalDepthStencil();

const MaterialDepthStencil& getDefinition() const;
void bind(id<MTLRenderCommandEncoder> descriptor);

private:
MetalVideo& video;
id<MTLDepthStencilState> state = nil;
MaterialDepthStencil definition;
int reference = 1;
};
}
105 changes: 105 additions & 0 deletions src/plugins/metal/src/metal_depth_stencil.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "metal_depth_stencil.h"
#include "metal_video.h"
using namespace Halley;

static MTLCompareFunction getComparisonFunc(DepthStencilComparisonFunction f)
{
switch (f) {
case DepthStencilComparisonFunction::Always:
return MTLCompareFunctionAlways;
case DepthStencilComparisonFunction::Never:
return MTLCompareFunctionNever;
case DepthStencilComparisonFunction::Equal:
return MTLCompareFunctionEqual;
case DepthStencilComparisonFunction::NotEqual:
return MTLCompareFunctionNotEqual;
case DepthStencilComparisonFunction::Less:
return MTLCompareFunctionLess;
case DepthStencilComparisonFunction::LessEqual:
return MTLCompareFunctionLessEqual;
case DepthStencilComparisonFunction::Greater:
return MTLCompareFunctionGreater;
case DepthStencilComparisonFunction::GreaterEqual:
return MTLCompareFunctionGreaterEqual;
}

return MTLCompareFunctionNever;
}

static MTLStencilOperation getOperation(StencilWriteOperation op)
{
switch (op) {
case StencilWriteOperation::Zero:
return MTLStencilOperationZero;
case StencilWriteOperation::Invert:
return MTLStencilOperationInvert;
case StencilWriteOperation::Keep:
return MTLStencilOperationKeep;
case StencilWriteOperation::Replace:
return MTLStencilOperationReplace;
case StencilWriteOperation::IncrementClamp:
return MTLStencilOperationIncrementClamp;
case StencilWriteOperation::IncrementWrap:
return MTLStencilOperationIncrementWrap;
case StencilWriteOperation::DecrementClamp:
return MTLStencilOperationDecrementClamp;
case StencilWriteOperation::DecrementWrap:
return MTLStencilOperationDecrementWrap;
}
return MTLStencilOperationKeep;
}

MetalDepthStencil::MetalDepthStencil(MetalVideo& video, const MaterialDepthStencil& definition)
: video(video)
, definition(definition)
{
MTLDepthStencilDescriptor * desc = [[MTLDepthStencilDescriptor alloc] init];

desc.depthWriteEnabled = definition.isDepthWriteEnabled();
desc.depthCompareFunction = getComparisonFunc(definition.isDepthTestEnabled() ? definition.getDepthComparisonFunction() : DepthStencilComparisonFunction::Always);

if( definition.isStencilTestEnabled() ) {

MTLStencilDescriptor *stencil_desc = [[MTLStencilDescriptor alloc] init];

stencil_desc.readMask = definition.getStencilReadMask();
stencil_desc.writeMask = definition.getStencilWriteMask();

stencil_desc.stencilFailureOperation = getOperation(definition.getStencilOpStencilFail());
stencil_desc.depthFailureOperation = getOperation(definition.getStencilOpDepthFail());
stencil_desc.depthStencilPassOperation = getOperation(definition.getStencilOpPass());
stencil_desc.stencilCompareFunction = getComparisonFunc(definition.getStencilComparisonFunction());

desc.frontFaceStencil = stencil_desc;
desc.backFaceStencil = stencil_desc;

reference = definition.getStencilReference();
}

state = [video.getDevice() newDepthStencilStateWithDescriptor:desc];
if (state == nil) {
throw Exception("Unable to create DepthStencil state", HalleyExceptions::VideoPlugin);
}
}

MetalDepthStencil::~MetalDepthStencil()
{
if (state) {
[state release];
state = nullptr;
}
}

const MaterialDepthStencil& MetalDepthStencil::getDefinition() const
{
return definition;
}

void MetalDepthStencil::bind( id<MTLRenderCommandEncoder> encoder )
{
[encoder setDepthStencilState: state];
if (definition.isStencilTestEnabled())
{
[encoder setStencilReferenceValue: reference];
}
}
6 changes: 3 additions & 3 deletions src/plugins/metal/src/metal_material_constant_buffer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
void MetalMaterialConstantBuffer::update(gsl::span<const gsl::byte> data) {
// We must pad up to a multiple of 16 (float4)
// TODO we ought to move this somewhere it won't be called so often.
const size_t padding = alignUp<char>(data.size_bytes(), 16);
const size_t padded_size = alignUp<size_t>(data.size_bytes(), 16);

auto padded = malloc(data.size_bytes() + padding);
auto padded = malloc(padded_size);
memcpy(padded, data.data(), data.size_bytes());

buffer.setData(gsl::span{reinterpret_cast<gsl::byte *>(padded),
static_cast<std::size_t>(static_cast<long>(data.size_bytes() + padding))});
static_cast<std::size_t>(static_cast<long>(padded_size))});

free(padded);
}
Expand Down
17 changes: 15 additions & 2 deletions src/plugins/metal/src/metal_painter.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once
#include <halley/graphics/painter.h>
#include <Metal/Metal.h>
#include "metal_depth_stencil.h"
#include "metal_render_target.h"

namespace Halley {
class MetalVideo;
Expand All @@ -19,16 +21,27 @@ namespace Halley {
void setClip(Rect4i clip, bool enable) override;
void setMaterialData(const Material& material) override;
void onUpdateProjection(Material& material, bool hashChanged) override;
void startEncoding(id<MTLTexture> texture);
void startEncoding(IMetalRenderTarget * renderTarget);
void endEncoding();

private:
void setBlending(BlendType blendType, MTLRenderPipelineColorAttachmentDescriptor* colorAttachment);
void setDepthStencil(const MaterialDepthStencil& depthStencilDefinition);
void setBlendFactor(MTLRenderPipelineColorAttachmentDescriptor* colorAttachment, MTLBlendFactor src, MTLBlendFactor dst);
MTLRenderPassDescriptor* renderPassDescriptorForTextureAndColour(id<MTLTexture> texture, Colour& colour);
MTLRenderPassDescriptor* renderPassDescriptorForTexture(id<MTLTexture> texture, id<MTLTexture> depthTexture);
void ensureEncoder();

MetalDepthStencil& getDepthStencil(const MaterialDepthStencil& depthStencilDefinition);

MetalVideo& video;
id<MTLRenderCommandEncoder> encoder;
id<MTLBuffer> indexBuffer;
MTLRenderPassDescriptor* nextRenderPassDescriptor;
IMetalRenderTarget *currentRenderTarget = nullptr;
std::optional<Rect4i> viewPort;
std::optional<Rect4i> clipRect;

HashMap<MaterialDepthStencil, std::unique_ptr<MetalDepthStencil>> depthStencils;
MetalDepthStencil* curDepthStencil = nullptr;
};
}
Loading