diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 5b14a58d8..302b21d38 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -157,6 +157,7 @@ 4B1EDB451E39A0AC009D6819 /* chip.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B1EDB431E39A0AC009D6819 /* chip.png */; }; 4B228CD524D773B40077EF25 /* CSScanTarget.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B228CD424D773B30077EF25 /* CSScanTarget.mm */; }; 4B228CD924DA12C60077EF25 /* CSScanTargetView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B228CD824DA12C60077EF25 /* CSScanTargetView.m */; }; + 4B228CDB24DA41890077EF25 /* ScanTarget.metal in Sources */ = {isa = PBXBuildFile; fileRef = 4B228CDA24DA41880077EF25 /* ScanTarget.metal */; }; 4B2530F4244E6774007980BF /* fm.json in Resources */ = {isa = PBXBuildFile; fileRef = 4B2530F3244E6773007980BF /* fm.json */; }; 4B2A332D1DB86821002876E3 /* OricOptions.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B2A332B1DB86821002876E3 /* OricOptions.xib */; }; 4B2A539F1D117D36003C6002 /* CSAudioQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A53911D117D36003C6002 /* CSAudioQueue.m */; }; @@ -1009,6 +1010,7 @@ 4B228CD624D773CA0077EF25 /* CSScanTarget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSScanTarget.h; sourceTree = ""; }; 4B228CD724DA12C50077EF25 /* CSScanTargetView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSScanTargetView.h; sourceTree = ""; }; 4B228CD824DA12C60077EF25 /* CSScanTargetView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSScanTargetView.m; sourceTree = ""; }; + 4B228CDA24DA41880077EF25 /* ScanTarget.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; name = ScanTarget.metal; path = "Clock Signal/ScanTarget/ScanTarget.metal"; sourceTree = ""; }; 4B24095A1C45DF85004DA684 /* Stepper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Stepper.hpp; sourceTree = ""; }; 4B2530F3244E6773007980BF /* fm.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = fm.json; sourceTree = ""; }; 4B2A332C1DB86821002876E3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/OricOptions.xib"; sourceTree = SOURCE_ROOT; }; @@ -3323,6 +3325,7 @@ 4BB73E951B587A5100552FC2 = { isa = PBXGroup; children = ( + 4B228CDA24DA41880077EF25 /* ScanTarget.metal */, 4BC3C67A24C9230F0027BF76 /* BufferingScanTarget.cpp */, 4BC3C67B24C9230F0027BF76 /* BufferingScanTarget.hpp */, 4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */, @@ -4687,6 +4690,7 @@ 4BA61EB01D91515900B3C876 /* NSData+StdVector.mm in Sources */, 4BDA00E022E644AF00AC3CD0 /* CSROMReceiverView.m in Sources */, 4BD191F42191180E0042E144 /* ScanTarget.cpp in Sources */, + 4B228CDB24DA41890077EF25 /* ScanTarget.metal in Sources */, 4B228CD524D773B40077EF25 /* CSScanTarget.mm in Sources */, 4BCD634922D6756400F567F1 /* MacintoshDoubleDensityDrive.cpp in Sources */, 4B0F94FE208C1A1600FE41D9 /* NIB.cpp in Sources */, diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm index a423db496..d378305ff 100644 --- a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm +++ b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm @@ -12,12 +12,43 @@ @implementation CSScanTarget { id _commandQueue; + + // TEST ONLY: to check that I'm drawing _something_, I'm heading towards ye standard + // Gouraud shading triangle. https://metalbyexample.com/up-and-running-2/ is providing + // much of the inspiration, albeit that I'm proceeding via MKLView. + id _vertexShader; + id _fragmentShader; + id _positionBuffer; + id _colourBuffer; + id _gouraudPipeline; } - (nonnull instancetype)initWithView:(nonnull MTKView *)view { self = [super init]; if(self) { _commandQueue = [view.device newCommandQueue]; + + // Generate some static buffers. AS A TEST. + constexpr float positions[] = { + 0.0f, 0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.0f, 1.0f, + }; + constexpr float colours[] = { + 1.0f, 0.0f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, + }; + _positionBuffer = [view.device newBufferWithBytes:positions length:sizeof(positions) options:MTLResourceOptionCPUCacheModeDefault]; + _colourBuffer = [view.device newBufferWithBytes:colours length:sizeof(colours) options:MTLResourceOptionCPUCacheModeDefault]; + + // Generate TEST pipeline. + id library = [view.device newDefaultLibrary]; + MTLRenderPipelineDescriptor *pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; + pipelineDescriptor.vertexFunction = [library newFunctionWithName:@"vertex_main"]; + pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"fragment_main"]; + pipelineDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat; + _gouraudPipeline = [view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil]; } return self; } @@ -30,7 +61,8 @@ @param size New drawable size in pixels */ - (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { - NSLog(@"New size: %@", NSStringFromSize(size)); + // I think (?) I don't care about this; the MKLView has already handled resizing the backing, + // which will naturally change the viewport. } /*! @@ -39,12 +71,18 @@ @discussion Called on the delegate when it is asked to render into the view */ - (void)drawInMTKView:(nonnull MTKView *)view { + // Generate a command encoder for the view. id commandBuffer = [_commandQueue commandBuffer]; MTLRenderPassDescriptor *const descriptor = view.currentRenderPassDescriptor; id encoder = [commandBuffer renderCommandEncoderWithDescriptor:descriptor]; - // TODO: the drawing (!) + // Drawing. Just the test triangle, as described above. + [encoder setRenderPipelineState:_gouraudPipeline]; + [encoder setVertexBuffer:_positionBuffer offset:0 atIndex:0]; + [encoder setVertexBuffer:_colourBuffer offset:0 atIndex:1]; + [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3 instanceCount:1]; + // Complete encoding. [encoder endEncoding]; // "Register the drawable's presentation". diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal b/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal new file mode 100644 index 000000000..6e5e1bef3 --- /dev/null +++ b/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal @@ -0,0 +1,28 @@ +// +// ScanTarget.metal +// Clock Signal +// +// Created by Thomas Harte on 04/08/2020. +// Copyright © 2020 Thomas Harte. All rights reserved. +// + +#include +using namespace metal; + +struct ColoredVertex { + float4 position [[position]]; + float4 color; +}; + +vertex ColoredVertex vertex_main( constant float4 *position [[buffer(0)]], + constant float4 *color [[buffer(1)]], + uint vid [[vertex_id]]) { + ColoredVertex vert; + vert.position = position[vid]; + vert.color = color[vid]; + return vert; +} + +fragment float4 fragment_main(ColoredVertex vert [[stage_in]]) { + return vert.color; +}