Skip to content

Commit

Permalink
get hydra successfully rendering on metal.
Browse files Browse the repository at this point in the history
Signed-off-by: furby™ <[email protected]>
  • Loading branch information
furby-tm committed Dec 30, 2024
1 parent 6a45a36 commit 9977b60
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 62 deletions.
4 changes: 3 additions & 1 deletion Sources/HgiMetal/include/HgiMetal/texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include <Metal/Metal.h>

#include "Arch/swiftInterop.h"

#include "Hgi/texture.h"
#include "HgiMetal/api.h"
#include "pxr/pxrns.h"
Expand Down Expand Up @@ -59,7 +61,7 @@ class HgiMetalTexture final : public HgiTexture {
HgiMetalTexture(const HgiMetalTexture &) = delete;

id<MTLTexture> _textureId;
};
} SWIFT_IMMORTAL_REFERENCE;

PXR_NAMESPACE_CLOSE_SCOPE

Expand Down
3 changes: 3 additions & 0 deletions Sources/UsdView/Hydra/Hydra+RenderEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public enum Hydra
sceneDelegateId: Sdf.Path.absoluteRootPath(),
driver: driver
)

engine.setEnablePresentation(false)
engine.setRenderer(aov: .color)
}

public func render(at timeCode: Double, viewSize: CGSize) -> Pixar.HgiTextureHandle
Expand Down
4 changes: 2 additions & 2 deletions Sources/UsdView/Hydra/Hydra+View.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ public extension Hydra

public extension Hydra.Viewport
{
init(engine: Hydra.RenderEngine, rgba: (Double, Double, Double, Double))
init(engine: Hydra.RenderEngine)
{
#if canImport(Metal) && !os(visionOS)
let renderer = Hydra.MTLRenderer(device: engine.hydraDevice, hydra: engine)
self.init(hydra: engine, renderer: renderer, rgba: rgba)
self.init(hydra: engine, renderer: renderer)
#endif // canImport(Metal) && !os(visionOS)
}
}
27 changes: 25 additions & 2 deletions Sources/UsdView/Hydra/MTL/Hydra+MTLRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import PixarUSD
private var hydra: Hydra.RenderEngine?
private var pipelineState: MTLRenderPipelineState?

private var inFlightSemaphore = DispatchSemaphore(value: 1)
private var inFlightSemaphore = DispatchSemaphore(value: 3)

convenience init(device: MTLDevice, hydra: Hydra.RenderEngine)
{
Expand Down Expand Up @@ -87,6 +87,11 @@ import PixarUSD

public func draw(in view: MTKView)
{
view.drawableSize = CGSize(
width: (view.frame.size.width > 0) ? view.frame.size.width : 400,
height: (view.frame.size.height > 0) ? view.frame.size.height : 300
)

drawFrame(in: view, timeCode: 0.0)
}

Expand All @@ -109,7 +114,7 @@ import PixarUSD
let viewSize = view.drawableSize
guard
let hgiTexture = hydra?.render(at: timeCode, viewSize: viewSize),
let metalTexture = hgiTexture.GetId() as? MTLTexture,
let metalTexture = getMetalTexture(from: hgiTexture),
let commandBuffer = hgi.pointee.GetPrimaryCommandBuffer()
else { Msg.logger.error("HYDRA: Failed to draw the scene."); return false }

Expand Down Expand Up @@ -154,6 +159,24 @@ import PixarUSD
commandBuffer.present(drawable)
}
}

public func getMetalTexture(from hgiTexture: Pixar.HgiTextureHandle) -> MTLTexture?
{
// get the hgi texture handle.
guard let hgiTex = hgiTexture.Get()
else { Msg.logger.error("HYDRA: Failed to retrieve the hgi texture."); return nil }

// get the raw pointer from the hgi handle.
let rawPtr = UnsafeRawPointer(hgiTex)

// get the hgi texture from the raw pointer.
let texPtr: Pixar.HgiMetalTexture = Unmanaged.fromOpaque(rawPtr).takeUnretainedValue()

// get the metal texture from the hgi texture.
let metalTexture = texPtr.GetTextureId()

return metalTexture
}
}
}
#endif // canImport(Metal) && !os(visionOS)
35 changes: 22 additions & 13 deletions Sources/UsdView/Hydra/MTL/Hydra+MTLView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,48 +38,57 @@ import PixarUSD
private let device: MTLDevice!
private let renderer: MTLRenderer!

var rgba: (Double, Double, Double, Double)

public init(hydra: Hydra.RenderEngine, renderer: MTLRenderer, rgba: (Double, Double, Double, Double))
public init(hydra: Hydra.RenderEngine, renderer: MTLRenderer)
{
self.hydra = hydra
self.device = hydra.hydraDevice
device = hydra.hydraDevice
self.renderer = renderer
self.rgba = rgba
}

public func makeCoordinator() -> Coordinator
{
Coordinator()
let mtkView = MTKView()
mtkView.isPaused = false
mtkView.framebufferOnly = true
if let mode = CGDisplayCopyDisplayMode(CGMainDisplayID())
{
mtkView.preferredFramesPerSecond = Int(mode.refreshRate)
}
else
{
mtkView.preferredFramesPerSecond = 60
}
mtkView.drawableSize = mtkView.frame.size

return Coordinator(mtkView: mtkView)
}

public func makeNSView(context: Context) -> MTKView
{
let metalView = context.coordinator.metalView

metalView.device = device
metalView.delegate = renderer
metalView.clearColor = MTLClearColorMake(rgba.0, rgba.1, rgba.2, rgba.3)
metalView.apply(context.environment)

context.coordinator.setNeedsDisplayTrigger = context.environment.setNeedsDisplayTrigger

metalView.becomeFirstResponder()
return metalView
}

public func updateNSView(_ view: MTKView, context: Context)
public func updateNSView(_ view: MTKView, context _: Context)
{
renderer.draw(in: view)
}

public class Coordinator
{
private var cancellable: AnyCancellable?
public var metalView: MTKView = .init(frame: .zero)
public var metalView: MTKView

public init()
public init(mtkView: MTKView)
{
cancellable = nil
setNeedsDisplayTrigger = nil
metalView = mtkView
}

public var setNeedsDisplayTrigger: SetNeedsDisplayTrigger?
Expand Down
14 changes: 1 addition & 13 deletions Sources/UsdView/UsdView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ struct UsdView: PixarApp
/// the hydra rendering engine.
let engine: Hydra.RenderEngine

/// give it a color spectrum...
@State var rgba = (0.1, 0.1, 0.1, 1.0)
@State var hue = 0.0

public init()
{
// register all usd plugins & resources.
Expand All @@ -61,15 +57,7 @@ struct UsdView: PixarApp
{
WindowGroup("UsdView", id: "usdview")
{
VStack
{
Hydra.Viewport(engine: engine, rgba: rgba)
.ignoresSafeArea()
}
.onAppear
{
startColorAnimation()
}
Hydra.Viewport(engine: engine)
}
}
}
31 changes: 0 additions & 31 deletions Sources/UsdView/Utils/ShadingUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,34 +62,3 @@ public func matDef(_ stage: UsdStageRefPtr, color: ShadeColor = ShadeColor.white

return material
}

#if canImport(SwiftUI)
import SwiftUI

extension UsdView
{
func startColorAnimation()
{
Timer.scheduledTimer(withTimeInterval: 0.03, repeats: true)
{ _ in
hue += 0.01
if hue > 1.0 { hue = 0.0 }
rgba = hueToRGBA(hue: hue)
}
}

func hueToRGBA(hue: Double) -> (Double, Double, Double, Double)
{
let color = Color(hue: hue, saturation: 1.0, brightness: 1.0)
var red: Double = 0, green: Double = 0, blue: Double = 0, alpha: Double = 0
if let components = color.cgColor?.components, components.count >= 3
{
red = components[0]
green = components[1]
blue = components[2]
alpha = Double(color.cgColor?.alpha ?? 1.0)
}
return (red, green, blue, alpha)
}
}
#endif // canImport(SwiftUI)

0 comments on commit 9977b60

Please sign in to comment.