mirror of
https://github.com/whoahq/whoa.git
synced 2026-03-18 05:31:07 +03:00
feat: Add debug rendering pipeline to draw a triangle in the Metal backend.
This commit is contained in:
parent
a9cad5238d
commit
81970958a8
@ -39,9 +39,13 @@ class CGxDeviceMTL : public CGxDevice {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void ISetCaps(const CGxFormat& format);
|
void ISetCaps(const CGxFormat& format);
|
||||||
|
void EnsureDebugPipeline();
|
||||||
void* m_device = nullptr;
|
void* m_device = nullptr;
|
||||||
void* m_commandQueue = nullptr;
|
void* m_commandQueue = nullptr;
|
||||||
void* m_layer = nullptr;
|
void* m_layer = nullptr;
|
||||||
|
void* m_pipeline = nullptr;
|
||||||
|
void* m_vertexBuffer = nullptr;
|
||||||
|
uint32_t m_vertexCount = 0;
|
||||||
uint32_t m_clearMask = 0;
|
uint32_t m_clearMask = 0;
|
||||||
uint32_t m_clearColor = 0;
|
uint32_t m_clearColor = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,6 +10,40 @@
|
|||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
#import <QuartzCore/CAMetalLayer.h>
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct DebugVertex {
|
||||||
|
float position[2];
|
||||||
|
float color[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
const DebugVertex kDebugTriangle[] = {
|
||||||
|
{ { -0.6f, -0.6f }, { 1.0f, 0.2f, 0.2f, 1.0f } },
|
||||||
|
{ { 0.0f, 0.6f }, { 0.2f, 1.0f, 0.2f, 1.0f } },
|
||||||
|
{ { 0.6f, -0.6f }, { 0.2f, 0.2f, 1.0f, 1.0f } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const char kDebugShaderSource[] =
|
||||||
|
"#include <metal_stdlib>\n"
|
||||||
|
"using namespace metal;\n"
|
||||||
|
"struct VertexIn {\n"
|
||||||
|
" packed_float2 position;\n"
|
||||||
|
" packed_float4 color;\n"
|
||||||
|
"};\n"
|
||||||
|
"struct VertexOut {\n"
|
||||||
|
" float4 position [[position]];\n"
|
||||||
|
" float4 color;\n"
|
||||||
|
"};\n"
|
||||||
|
"vertex VertexOut vs_main(uint vid [[vertex_id]], const device VertexIn* v [[buffer(0)]]) {\n"
|
||||||
|
" VertexOut out;\n"
|
||||||
|
" out.position = float4(v[vid].position, 0.0, 1.0);\n"
|
||||||
|
" out.color = v[vid].color;\n"
|
||||||
|
" return out;\n"
|
||||||
|
"}\n"
|
||||||
|
"fragment float4 ps_main(VertexOut in [[stage_in]]) {\n"
|
||||||
|
" return in.color;\n"
|
||||||
|
"}\n";
|
||||||
|
}
|
||||||
|
|
||||||
CGxDeviceMTL::CGxDeviceMTL() : CGxDevice() {
|
CGxDeviceMTL::CGxDeviceMTL() : CGxDevice() {
|
||||||
this->m_api = GxApi_Metal;
|
this->m_api = GxApi_Metal;
|
||||||
this->m_caps.m_colorFormat = GxCF_rgba;
|
this->m_caps.m_colorFormat = GxCF_rgba;
|
||||||
@ -151,6 +185,63 @@ int32_t CGxDeviceMTL::DeviceSetFormat(const CGxFormat& format) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGxDeviceMTL::EnsureDebugPipeline() {
|
||||||
|
if (this->m_pipeline || !this->m_device || !this->m_layer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto device = (id<MTLDevice>)this->m_device;
|
||||||
|
auto layer = (CAMetalLayer*)this->m_layer;
|
||||||
|
|
||||||
|
NSString* source = [[NSString alloc] initWithUTF8String:kDebugShaderSource];
|
||||||
|
NSError* error = nil;
|
||||||
|
id<MTLLibrary> library = [device newLibraryWithSource:source options:nil error:&error];
|
||||||
|
[source release];
|
||||||
|
|
||||||
|
if (!library) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
id<MTLFunction> vs = [library newFunctionWithName:@"vs_main"];
|
||||||
|
id<MTLFunction> ps = [library newFunctionWithName:@"ps_main"];
|
||||||
|
if (!vs || !ps) {
|
||||||
|
if (vs) {
|
||||||
|
[vs release];
|
||||||
|
}
|
||||||
|
if (ps) {
|
||||||
|
[ps release];
|
||||||
|
}
|
||||||
|
[library release];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new];
|
||||||
|
desc.vertexFunction = vs;
|
||||||
|
desc.fragmentFunction = ps;
|
||||||
|
desc.colorAttachments[0].pixelFormat = layer.pixelFormat;
|
||||||
|
|
||||||
|
id<MTLRenderPipelineState> pipeline = [device newRenderPipelineStateWithDescriptor:desc error:&error];
|
||||||
|
[desc release];
|
||||||
|
[vs release];
|
||||||
|
[ps release];
|
||||||
|
[library release];
|
||||||
|
|
||||||
|
if (!pipeline) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
id<MTLBuffer> buffer = [device newBufferWithBytes:kDebugTriangle
|
||||||
|
length:sizeof(kDebugTriangle)
|
||||||
|
options:MTLResourceStorageModeShared];
|
||||||
|
if (!buffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_pipeline = pipeline;
|
||||||
|
this->m_vertexBuffer = buffer;
|
||||||
|
this->m_vertexCount = static_cast<uint32_t>(sizeof(kDebugTriangle) / sizeof(kDebugTriangle[0]));
|
||||||
|
}
|
||||||
|
|
||||||
void* CGxDeviceMTL::DeviceWindow() {
|
void* CGxDeviceMTL::DeviceWindow() {
|
||||||
return &this->m_window;
|
return &this->m_window;
|
||||||
}
|
}
|
||||||
@ -204,6 +295,8 @@ void CGxDeviceMTL::ScenePresent() {
|
|||||||
|
|
||||||
System_Autorelease::ScopedPool autorelease;
|
System_Autorelease::ScopedPool autorelease;
|
||||||
|
|
||||||
|
this->EnsureDebugPipeline();
|
||||||
|
|
||||||
id<CAMetalDrawable> drawable = [layer nextDrawable];
|
id<CAMetalDrawable> drawable = [layer nextDrawable];
|
||||||
if (!drawable) {
|
if (!drawable) {
|
||||||
return;
|
return;
|
||||||
@ -216,17 +309,22 @@ void CGxDeviceMTL::ScenePresent() {
|
|||||||
|
|
||||||
auto pass = [MTLRenderPassDescriptor renderPassDescriptor];
|
auto pass = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
pass.colorAttachments[0].texture = drawable.texture;
|
pass.colorAttachments[0].texture = drawable.texture;
|
||||||
pass.colorAttachments[0].loadAction = (this->m_clearMask & 0x1) ? MTLLoadActionClear : MTLLoadActionLoad;
|
pass.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||||
pass.colorAttachments[0].storeAction = MTLStoreActionStore;
|
pass.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||||
pass.colorAttachments[0].clearColor = MTLClearColorMake(
|
pass.colorAttachments[0].clearColor = MTLClearColorMake(
|
||||||
r / 255.0f,
|
(this->m_clearMask & 0x1) ? r / 255.0f : 0.0f,
|
||||||
g / 255.0f,
|
(this->m_clearMask & 0x1) ? g / 255.0f : 0.0f,
|
||||||
b / 255.0f,
|
(this->m_clearMask & 0x1) ? b / 255.0f : 0.0f,
|
||||||
a / 255.0f
|
(this->m_clearMask & 0x1) ? a / 255.0f : 1.0f
|
||||||
);
|
);
|
||||||
|
|
||||||
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
|
id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
|
||||||
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor: pass];
|
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor: pass];
|
||||||
|
if (encoder && this->m_pipeline && this->m_vertexBuffer) {
|
||||||
|
[encoder setRenderPipelineState:(id<MTLRenderPipelineState>)this->m_pipeline];
|
||||||
|
[encoder setVertexBuffer:(id<MTLBuffer>)this->m_vertexBuffer offset:0 atIndex:0];
|
||||||
|
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:this->m_vertexCount];
|
||||||
|
}
|
||||||
[encoder endEncoding];
|
[encoder endEncoding];
|
||||||
|
|
||||||
[commandBuffer presentDrawable: drawable];
|
[commandBuffer presentDrawable: drawable];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user