1 Reply
      Latest reply on Oct 4, 2019 3:32 PM by Nickkk
      Nickkk Level 1 Level 1 (0 points)

        I have some code that works fine on macOS 10.14, here is what I get:

         

        And here is what it looks like on macOS 10.15 (notice how the background is not blue anymore and the text, barely visible, is twice as wide and therefore gets cropped):

         

        Does anyone have an idea what could be the problem?

         

        Here is the code:

         

        AppDelegate.swift

        import Cocoa
        import MetalKit
        
        @NSApplicationMain
        class AppDelegate: NSObject, NSApplicationDelegate, MTKViewDelegate {
        
            struct Vertex {
                var position: vector_float2
                var textureCoordinates: vector_float2
          
                init(position: vector_float2, textureCoordinates: vector_float2) {
                    self.position = position
                    self.textureCoordinates = textureCoordinates
                }
            }
        
            @IBOutlet var window: NSWindow!
        
            var commandQueue: MTLCommandQueue!
            var texturePipelineState: MTLRenderPipelineState!
            var texture: MTLTexture!
            var textFrame = NSRect.zero
        
            func applicationWillFinishLaunching(_ aNotification: Notification) {
                let mtkView = window.contentView as! MTKView
                mtkView.delegate = self
                mtkView.clearColor = .init(red: 1, green: 1, blue: 1, alpha: 1)
                let device = MTLCreateSystemDefaultDevice()!
                mtkView.device = device
                mtkView.isPaused = true
                mtkView.enableSetNeedsDisplay = true
                let defaultLibrary = device.makeDefaultLibrary()!
                let texturePipelineDescriptor = MTLRenderPipelineDescriptor()
                texturePipelineDescriptor.vertexFunction = defaultLibrary.makeFunction(name: "textureVertexShader")
                texturePipelineDescriptor.fragmentFunction = defaultLibrary.makeFunction(name: "textureFragmentShader")
                texturePipelineDescriptor.colorAttachments[0].pixelFormat = mtkView.colorPixelFormat
                texturePipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
                texturePipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
                texturePipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .sourceAlpha
                texturePipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
                texturePipelineState = try! device.makeRenderPipelineState(descriptor: texturePipelineDescriptor)
                commandQueue = device.makeCommandQueue()
          
                let textureDescriptor = MTLTextureDescriptor()
                textureDescriptor.pixelFormat = mtkView.colorPixelFormat
                let attributedString = NSAttributedString(string: "asdf", attributes: [.font: NSFontManager.shared.convert(.labelFont(ofSize: 15), toHaveTrait: .boldFontMask), .foregroundColor: NSColor.white])
                let frameSize = attributedString.size()
                let image = NSImage(size: frameSize)
                image.lockFocus()
                textFrame = NSRect(x: 0, y: 0, width: frameSize.width, height: frameSize.height)
                if true {
                    NSColor.red.set()
                    NSBezierPath(rect: textFrame).fill()
                }
                attributedString.draw(in: textFrame)
                let bitmap = NSBitmapImageRep(focusedViewRect: textFrame)!
                image.unlockFocus()
                let textureSize = NSSize(width: CGFloat(bitmap.pixelsWide), height: CGFloat(bitmap.pixelsHigh))
                textureDescriptor.width = Int(textureSize.width)
                textureDescriptor.height = Int(textureSize.height)
                texture = device.makeTexture(descriptor: textureDescriptor)!
                let region = MTLRegionMake2D(0, 0, Int(textureSize.width), Int(textureSize.height))
                texture.replace(region: region, mipmapLevel: 0, withBytes: bitmap.bitmapData!, bytesPerRow: bitmap.bytesPerRow)
            }
        
            func draw(in view: MTKView) {
                guard let currentDrawable = view.currentDrawable, let renderPassDescriptor = view.currentRenderPassDescriptor else {
                    return
                }
                let commandBuffer = commandQueue.makeCommandBuffer()!
                let renderCommandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)!
                let viewSize = view.frame.size
                var viewportSize = vector_uint2(x: UInt32(viewSize.width), y: UInt32(viewSize.height))
                renderCommandEncoder.setVertexBytes(&viewportSize, length: MemoryLayout<vector_uint2>.size, index: Int(VertexInputIndexViewportSize.rawValue))
          
                renderCommandEncoder.setRenderPipelineState(texturePipelineState)
                let vertices = [Vertex(position: vector_float2(Float(textFrame.minX), Float(textFrame.minY)), textureCoordinates: vector_float2(0, 1)),
                                Vertex(position: vector_float2(Float(textFrame.maxX), Float(textFrame.minY)), textureCoordinates: vector_float2(1, 1)),
                                Vertex(position: vector_float2(Float(textFrame.minX), Float(textFrame.maxY)), textureCoordinates: vector_float2(0, 0)),
                                Vertex(position: vector_float2(Float(textFrame.maxX), Float(textFrame.maxY)), textureCoordinates: vector_float2(1, 0))]
                renderCommandEncoder.setVertexBytes(vertices, length: MemoryLayout.size * vertices.count, index: Int(VertexInputIndexVertices.rawValue))
                renderCommandEncoder.setFragmentTexture(texture, index: Int(FragmentInputIndexTexture.rawValue))
                renderCommandEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
        
                renderCommandEncoder.endEncoding()
                commandBuffer.present(currentDrawable)
                commandBuffer.commit()
            }
        
            func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
            }
        
        }

         

        ShaderTypes.h

        #import 
        
        typedefenum VertexInputIndex: int {
            VertexInputIndexVertices = 0,
            VertexInputIndexViewportSize = 1,
        } VertexInputIndex;
        
        typedef enum FragmentInputIndex: int {
            FragmentInputIndexTexture = 0,
        } FragmentInputIndex;
        
        typedef struct {
            vector_float2 position;
            vector_float2 textureCoordinates;
        } Vertex;

         

        Shaders.metal

        #include <metal_stdlib>
        #include "ShaderTypes.h"
        
        using namespace metal;
        
        typedef struct {
            float4 clipSpacePosition [[position]];
            float2 textureCoordinates;
        } TextureRasterizerData;
        
        vertex TextureRasterizerData textureVertexShader(uint vertexID [[vertex_id]],
                                                  constant Vertex *texturedVertices [[buffer(VertexInputIndexVertices)]],
                                                  constant vector_uint2 *viewportSizePointer [[buffer(VertexInputIndexViewportSize)]]) {
            TextureRasterizerData out;
            out.clipSpacePosition = float4(0.0, 0.0, 0.0, 1.0);
            float2 pixelSpacePosition = texturedVertices[vertexID].position;
            float2 viewportSize = float2(*viewportSizePointer);
            out.clipSpacePosition.xy = pixelSpacePosition / (viewportSize / 2.0);
            out.textureCoordinates = texturedVertices[vertexID].textureCoordinates;
            return out;
        }
        
        constexpr sampler textureSampler (mag_filter::linear, min_filter::linear);
        
        fragment float4 textureFragmentShader(TextureRasterizerData in [[stage_in]],
                                       texture2d colorTexture [[texture(FragmentInputIndexTexture)]]) {
            half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinates);
            return float4(colorSample);
        }