This commit is contained in:
vfs committed 2026-05-16 17:20:07 +02:00
1 parent 6883d103ff
commit e43edc67bd
10 files changed
+74 -62

No files matched your search

+10 -2
View File
@@ -39,6 +39,8 @@ void upload_texture(
const void *pixels,
Texture *texture)
{
texture->p_texture = new PlatformTexture{};
MTL::TextureDescriptor *td = MTL::TextureDescriptor::alloc()->init();
td->setPixelFormat(MTL::PixelFormatRGBA8Unorm);
td->setWidth(w);
@@ -73,13 +75,15 @@ void create_metal_layer(GLFWwindow *window) {
SEL setLayerSel = sel_registerName("setLayer:");
((void (*)(id, SEL, id))objc_msgSend)(content_view, setLayerSel, (id)metal_layer);
metal_layer->retain();
metal_layer->setDevice(metal_device.device);
metal_layer->setPixelFormat(MTL::PixelFormatRGBA16Float);
metal_layer->setFramebufferOnly(true);
metal_layer->setDrawableSize(CGSizeMake(800, 600));
int fb_w, fb_h;
glfwGetFramebufferSize(window, &fb_w, &fb_h);
metal_layer->setDrawableSize(CGSizeMake(fb_w, fb_h));
CGColorSpaceRef p3Space = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
metal_layer->setColorspace(p3Space);
CGColorSpaceRelease(p3Space);
}
void load_metal_shader(const std::string &shader_path,
@@ -201,6 +205,10 @@ void end_frame(GLFWwindow *window) {
pPool->release();
}
void submit_quad(glm::vec2 pos, glm::vec2 scale) {
renderer.submit_quad({pos.x, pos.y}, {scale.x, scale.y});
}
void submit_sprite(glm::vec2 pos, const sprite_t &sprite) {
renderer.submit_sprite({pos.x, pos.y}, sprite);
}
+1 -1
View File
@@ -7,7 +7,7 @@
#include <GLFW/glfw3.h>
#define GLFW_EXPOSE_NATIVE_COCOA
#import <GLFW/glfw3native.h>
#include <GLFW/glfw3native.h>
#include <Metal/Metal.hpp>
#include <QuartzCore/CAMetalLayer.hpp>
+37 -49
View File
@@ -65,7 +65,7 @@ void Renderer::submit_quad(simd::float2 pos, simd::float2 scale) {
RenderCommand cmd {};
cmd.pipeline = PipelineType::ColoredQuad;
cmd.key = {
(uint16_t) pos.y,
(uint16_t) pos[1],
0,
(uint8_t) PipelineType::ColoredQuad
};
@@ -83,7 +83,7 @@ void Renderer::submit_sprite(simd::float2 pos, const sprite_t &sprite) {
RenderCommand cmd {};
cmd.pipeline = PipelineType::TexturedQuad;
cmd.key = {
(uint16_t) pos.y,
(uint16_t) pos[1],
0,
(uint8_t) PipelineType::TexturedQuad
};
@@ -247,6 +247,14 @@ void Renderer::create_render_pipeline() {
}
renderPipelineDescriptor->release();
vd->release();
vertex_shader->release();
fragment_shader->release();
MTL::SamplerDescriptor *sampler_desc = MTL::SamplerDescriptor::alloc()->init();
sampler_desc->setMinFilter(MTL::SamplerMinMagFilterLinear);
sampler_desc->setMagFilter(MTL::SamplerMinMagFilterLinear);
sampler_state = metal_device.device->newSamplerState(sampler_desc);
sampler_desc->release();
}
float4x4 make_ortho(float left, float right, float bottom, float top, float near, float far) {
@@ -267,46 +275,34 @@ float4x4 make_ortho(float left, float right, float bottom, float top, float near
}
void Renderer::encode_render_command(GLFWwindow *window, MTL::RenderCommandEncoder *render_command_encoder) {
struct DrawGroup {
MTL::Texture *texture;
NS::UInteger vertex_start;
NS::UInteger vertex_count;
};
std::vector<vertex_p2_s2_uv2_c4_a1> vertices;
std::vector<DrawGroup> groups;
for (auto& cmd : commands) {
switch (cmd.pipeline) {
case PipelineType::ColoredQuad: {
const auto &q = cmd.colored_quad;
vertex_p2_s2_uv2_c4_a1 vTL = { q.pos, q.scale, {}, q.colour };
vertex_p2_s2_uv2_c4_a1 vTR = { q.pos, q.scale, {}, q.colour };
vertex_p2_s2_uv2_c4_a1 vBL = { q.pos, q.scale, {}, q.colour };
vertex_p2_s2_uv2_c4_a1 vBR = { q.pos, q.scale, {}, q.colour };
vertices.push_back(vTL);
vertices.push_back(vBL);
vertices.push_back(vTR);
vertices.push_back(vTR);
vertices.push_back(vBL);
vertices.push_back(vBR);
break;
}
case PipelineType::TexturedQuad: {
const auto &q = cmd.textured_quad;
if (!q.texture) break;
vertex_p2_s2_uv2_c4_a1 vTL = { q.pos, q.scale, q.uv0, q.colour, 1.0 };
vertex_p2_s2_uv2_c4_a1 vTR = { q.pos, q.scale, {q.uv1.x, q.uv0.y}, q.colour, 1.0 };
vertex_p2_s2_uv2_c4_a1 vBL = { q.pos, q.scale, {q.uv0.x, q.uv1.y}, q.colour, 1.0 };
vertex_p2_s2_uv2_c4_a1 vBR = { q.pos, q.scale, q.uv1, q.colour, 1.0};
if (groups.empty() || groups.back().texture != q.texture)
groups.push_back({q.texture, (NS::UInteger)vertices.size(), 0});
vertices.push_back(vTL);
vertices.push_back(vBL);
vertices.push_back(vTR);
vertices.push_back(vTR);
vertices.push_back(vBL);
vertices.push_back(vBR);
simd::float2 uv_tr = {q.uv1[0], q.uv0[1]};
simd::float2 uv_bl = {q.uv0[0], q.uv1[1]};
vertices.push_back({ q.pos, q.scale, q.uv0, q.colour, 1.0f });
vertices.push_back({ q.pos, q.scale, uv_bl, q.colour, 1.0f });
vertices.push_back({ q.pos, q.scale, uv_tr, q.colour, 1.0f });
vertices.push_back({ q.pos, q.scale, uv_tr, q.colour, 1.0f });
vertices.push_back({ q.pos, q.scale, uv_bl, q.colour, 1.0f });
vertices.push_back({ q.pos, q.scale, q.uv1, q.colour, 1.0f });
groups.back().vertex_count += 6;
break;
}
default:
@@ -314,33 +310,26 @@ void Renderer::encode_render_command(GLFWwindow *window, MTL::RenderCommandEncod
}
}
if (vertices.empty()) return;
const Frame &frame = frames[current_frame];
memcpy(frame.vertex_buffer->contents(), vertices.data(), vertices.size() * sizeof(vertex_p2_s2_uv2_c4_a1));
MTL::SamplerDescriptor* sampler_desc = MTL::SamplerDescriptor::alloc()->init();
sampler_desc->setMinFilter(MTL::SamplerMinMagFilterLinear);
sampler_desc->setMagFilter(MTL::SamplerMinMagFilterLinear);
MTL::SamplerState* sampler = metal_device.device->newSamplerState(sampler_desc);
int width, height;
glfwGetFramebufferSize(window, &width, &height);
simd::float4x4 ortho = make_ortho(0.0, window_width, window_height, 0.0, 1.0, 0.0);
simd::float4x4 ortho = make_ortho(0.0f, (float)width, (float)height, 0.0f, 1.0f, 0.0f);
auto tm = simd::transpose(ortho);
memcpy(frame.uniform_buffer->contents(), &tm, sizeof(ortho));
render_command_encoder->setRenderPipelineState(textured_quad_pipeline);
render_command_encoder->setVertexBuffer(frame.vertex_buffer, 0, 0);
render_command_encoder->setVertexBuffer(frame.uniform_buffer, 0, 1);
render_command_encoder->setFragmentSamplerState(sampler, 0);
MTL::PrimitiveType type_triangle = MTL::PrimitiveTypeTriangle;
NS::UInteger vertexStart = 0;
NS::UInteger vertexCount = vertices.size();
const Texture &texture = texture_manager.textures["assets/boy.png"];
render_command_encoder->setFragmentTexture(texture.p_texture->texture, 0);
render_command_encoder->drawPrimitives(type_triangle, vertexStart, vertexCount);
render_command_encoder->setFragmentSamplerState(sampler_state, 0);
sampler_desc->release();
for (const auto &group : groups) {
render_command_encoder->setFragmentTexture(group.texture, 0);
render_command_encoder->drawPrimitives(MTL::PrimitiveTypeTriangle, group.vertex_start, group.vertex_count);
}
}
void Renderer::send_render_command(GLFWwindow *window) {
@@ -371,7 +360,6 @@ void Renderer::send_render_command(GLFWwindow *window) {
command_buffer->presentDrawable(metal_drawable);
command_buffer->commit();
command_buffer->waitUntilCompleted();
current_frame = (current_frame + 1) % kMaxFramesInFlight;
+1
View File
@@ -114,6 +114,7 @@ struct Renderer {
uint32_t nextTextureSlot = 0;
MTL::SamplerState *sampler_state{};
MTL::CommandBuffer *command_buffer{};
struct Frame {