<commit_before>﻿#include "video_metal.h"
#include <halley/core/graphics/texture.h>
#include <halley/core/graphics/shader.h>
#include <halley/core/graphics/material/material_definition.h>
#include <SDL2/SDL.h>

using namespace Halley;

///////////////
// Constructor
VideoMetal::VideoMetal(SystemAPI& system)
  : system(system)
{
}

void VideoMetal::init()
{
}

void VideoMetal::deInit()
{
  std::cout << "Shutting down Metal..." << std::endl;
}

void VideoMetal::startRender()
{
  surface = [swap_chain nextDrawable];
}

void VideoMetal::finishRender()
{
  window->swap();
  [surface release];
}


void VideoMetal::setWindow(WindowDefinition&& windowDescriptor)
{
  window = system.createWindow(windowDescriptor);
  initSwapChain(*window);
}

void VideoMetal::initSwapChain(Window& window) {
  if (window.getNativeHandleType() != "SDL") {
    throw Exception("Only SDL2 windows are supported by Metal", HalleyExceptions::VideoPlugin);
  }
  SDL_Window* sdl_window = static_cast<SDL_Window*>(window.getNativeHandle());
  SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal");
  SDL_Renderer *renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_PRESENTVSYNC);
  swap_chain = static_cast<CAMetalLayer*>(SDL_RenderGetMetalLayer(renderer));
  SDL_DestroyRenderer(renderer);
  swap_chain.pixelFormat = MTLPixelFormatBGRA8Unorm;
  device = swap_chain.device;
  command_queue = [device newCommandQueue];
  std::cout << "\tGot Metal device: " << [device.name UTF8String] << std::endl;
}

const Window& VideoMetal::getWindow() const
{
  return *window;
}

bool VideoMetal::hasWindow() const
{
  return window != nullptr;
}


std::unique_ptr<Texture> VideoMetal::createTexture(Vector2i size)
{
  return std::make_unique<MetalTexture>(size);
}

std::unique_ptr<Shader> VideoMetal::createShader(const ShaderDefinition& definition)
{
  std::cout << "Creating shader for definition: " << definition.name << std::endl;
  std::cout << "Got " << definition.vertexAttributes.size() << " vertex attributes." << std::endl;
  for (auto const& attr : definition.vertexAttributes) {
    std::cout << "\tGot vertex attribute: " << attr.name << std::endl;
  }
  for (auto const& shader : definition.shaders) {
    std::cout << "\tGot shader: " << int(shader.first) << std::endl << std::string(shader.second.begin(), shader.second.end()) << std::endl;
    auto shaderSrc = std::string(shader.second.begin(), shader.second.end());
    auto compileOptions = [MTLCompileOptions new];
    NSError* compileError;
    id<MTLLibrary> lib = [device newLibraryWithSource:[NSString stringWithUTF8String:shaderSrc.c_str()] options:compileOptions error:&compileError];
    if (compileError) {
      throw Exception([[compileError localizedDescription] UTF8String], HalleyExceptions::VideoPlugin);
    }
    [compileOptions release];
    [compileError release];
  }
  return std::make_unique<MetalShader>();
}

std::unique_ptr<TextureRenderTarget> VideoMetal::createTextureRenderTarget()
{
  return std::make_unique<TextureRenderTarget>();
}

std::unique_ptr<ScreenRenderTarget> VideoMetal::createScreenRenderTarget()
{
  return std::make_unique<ScreenRenderTarget>(Rect4i({}, getWindow().getWindowRect().getSize()));
}<commit_msg>just compile combined shader<commit_after>﻿#include "video_metal.h"
#include <halley/core/graphics/texture.h>
#include <halley/core/graphics/shader.h>
#include <halley/core/graphics/material/material_definition.h>
#include <SDL2/SDL.h>

using namespace Halley;

///////////////
// Constructor
VideoMetal::VideoMetal(SystemAPI& system)
  : system(system)
{
}

void VideoMetal::init()
{
}

void VideoMetal::deInit()
{
  std::cout << "Shutting down Metal..." << std::endl;
}

void VideoMetal::startRender()
{
  surface = [swap_chain nextDrawable];
}

void VideoMetal::finishRender()
{
  window->swap();
  [surface release];
}


void VideoMetal::setWindow(WindowDefinition&& windowDescriptor)
{
  window = system.createWindow(windowDescriptor);
  initSwapChain(*window);
}

void VideoMetal::initSwapChain(Window& window) {
  if (window.getNativeHandleType() != "SDL") {
    throw Exception("Only SDL2 windows are supported by Metal", HalleyExceptions::VideoPlugin);
  }
  SDL_Window* sdl_window = static_cast<SDL_Window*>(window.getNativeHandle());
  SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal");
  SDL_Renderer *renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_PRESENTVSYNC);
  swap_chain = static_cast<CAMetalLayer*>(SDL_RenderGetMetalLayer(renderer));
  SDL_DestroyRenderer(renderer);
  swap_chain.pixelFormat = MTLPixelFormatBGRA8Unorm;
  device = swap_chain.device;
  command_queue = [device newCommandQueue];
  std::cout << "\tGot Metal device: " << [device.name UTF8String] << std::endl;
}

const Window& VideoMetal::getWindow() const
{
  return *window;
}

bool VideoMetal::hasWindow() const
{
  return window != nullptr;
}


std::unique_ptr<Texture> VideoMetal::createTexture(Vector2i size)
{
  return std::make_unique<MetalTexture>(size);
}

std::unique_ptr<Shader> VideoMetal::createShader(const ShaderDefinition& definition)
{
  std::cout << "Creating shader for definition: " << definition.name << std::endl;
  std::cout << "Got " << definition.vertexAttributes.size() << " vertex attributes." << std::endl;
  for (auto const& attr : definition.vertexAttributes) {
    std::cout << "\tGot vertex attribute: " << attr.name << std::endl;
  }
  if (definition.shaders.find(ShaderType::Combined) == definition.shaders.end()) {
    throw Exception("Metal requires combined shaders", HalleyExceptions::VideoPlugin);
  }
  auto shader = definition.shaders.at(ShaderType::Combined);
  auto shaderSrc = std::string(shader.begin(), shader.end());
  auto compileOptions = [MTLCompileOptions new];
  NSError* compileError;
  id<MTLLibrary> lib = [device newLibraryWithSource:[NSString stringWithUTF8String:shaderSrc.c_str()] options:compileOptions error:&compileError];
  if (compileError) {
    std::cout << "Metal shader compilation failed for material " << definition.name << std::endl;
    throw Exception([[compileError localizedDescription] UTF8String], HalleyExceptions::VideoPlugin);
  }
  [compileOptions release];
  [compileError release];
  return std::make_unique<MetalShader>();
}

std::unique_ptr<TextureRenderTarget> VideoMetal::createTextureRenderTarget()
{
  return std::make_unique<TextureRenderTarget>();
}

std::unique_ptr<ScreenRenderTarget> VideoMetal::createScreenRenderTarget()
{
  return std::make_unique<ScreenRenderTarget>(Rect4i({}, getWindow().getWindowRect().getSize()));
}
{'fraction_non_alphanumeric': 0.148330512386521, 'fraction_numerical': 0.0027696568702877365, 'mean_word_length': 6.246376811594203, 'pattern_counts': {'":': 0, '<': 109, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4722690', 'n_tokens_mistral': 2097, 'n_tokens_neox': 2036, 'n_words': 373}