public MTLRenderPassDescriptor GetRenderPassDescriptor(ICAMetalDrawable drawable) { if (drawable == null) { Console.WriteLine("ERROR: Failed to get a drawable!"); renderPassDescriptor = null; } else { SetupRenderPassDescriptorForTexture(drawable.Texture); } return(renderPassDescriptor); }
public void Draw(MTKView view) { // Update var time = clock.ElapsedMilliseconds / 1000.0f; var viewProj = Matrix4.Mult(this.view, this.proj); var worldViewProj = Matrix4.CreateRotationY(time * 2) * Matrix4.Scale(0.0015f) * viewProj; worldViewProj = Matrix4.Transpose(worldViewProj); this.param.WorldViewProjection = worldViewProj; SetConstantBuffer(this.param, constantBuffer); // Create a new command buffer for each renderpass to the current drawable IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer(); // Call the view's completion handler which is required by the view since it will signal its semaphore and set up the next buffer var drawable = view.CurrentDrawable; // Obtain a renderPassDescriptor generated from the view's drawable textures MTLRenderPassDescriptor renderPassDescriptor = view.CurrentRenderPassDescriptor; // If we have a valid drawable, begin the commands to render into it if (renderPassDescriptor != null) { // Create a render command encoder so we can render into something IMTLRenderCommandEncoder renderEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor); // Set context state renderEncoder.SetDepthStencilState(depthState); renderEncoder.SetRenderPipelineState(pipelineState); renderEncoder.SetVertexBuffer(objMesh.VertexBuffers[0].Buffer, objMesh.VertexBuffers[0].Offset, 0); renderEncoder.SetVertexBuffer(constantBuffer, (nuint)Marshal.SizeOf <Matrix4>(), 1); renderEncoder.SetFragmentTexture(this.texture, 0); renderEncoder.SetFragmentSamplerState(this.sampler, 0); for (int i = 0; i < objMesh.Submeshes.Length; i++) { MTKSubmesh submesh = objMesh.Submeshes[i]; renderEncoder.DrawIndexedPrimitives(submesh.PrimitiveType, submesh.IndexCount, submesh.IndexType, submesh.IndexBuffer.Buffer, submesh.IndexBuffer.Offset); } // We're done encoding commands renderEncoder.EndEncoding(); // Schedule a present once the framebuffer is complete using the current drawable commandBuffer.PresentDrawable(drawable); } // Finalize rendering here & push the command buffer to the GPU commandBuffer.Commit(); }
public void Draw(MTKView view) { // Create a new command buffer for each renderpass to the current drawable IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer(); // Compute commands IMTLComputeCommandEncoder computeCommandEncoder = commandBuffer.ComputeCommandEncoder; computeCommandEncoder.SetComputePipelineState(computePipelineState); computeCommandEncoder.SetBuffer(tessellationFactorsBuffer, 0, 2); computeCommandEncoder.DispatchThreadgroups(new MTLSize(1, 1, 1), new MTLSize(1, 1, 1)); computeCommandEncoder.EndEncoding(); // Render commands // Call the view's completion handler which is required by the view since it will signal its semaphore and set up the next buffer var drawable = view.CurrentDrawable; // Obtain a renderPassDescriptor generated from the view's drawable textures MTLRenderPassDescriptor renderPassDescriptor = view.CurrentRenderPassDescriptor; // Create a render command encoder so we can render into something IMTLRenderCommandEncoder renderCommandEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor); // Set context state renderCommandEncoder.SetTriangleFillMode(MTLTriangleFillMode.Lines); renderCommandEncoder.SetDepthStencilState(depthState); renderCommandEncoder.SetRenderPipelineState(renderPipelineState); renderCommandEncoder.SetVertexBuffer(controlPointsBuffer, 0, 0); renderCommandEncoder.SetTessellationFactorBuffer(tessellationFactorsBuffer, 0, 0); // Tell the render context we want to draw our primitives renderCommandEncoder.DrawPatches(3, 0, 1, null, 0, 1, 0); // We're done encoding commands renderCommandEncoder.EndEncoding(); // Schedule a present once the framebuffer is complete using the current drawable commandBuffer.PresentDrawable(drawable); // Finalize rendering here & push the command buffer to the GPU commandBuffer.Commit(); }
public override MTLRenderPassDescriptor CreateRenderPassDescriptor() { MTLRenderPassDescriptor ret = MTLRenderPassDescriptor.New(); var color0 = ret.colorAttachments[0]; color0.texture = _parentSwapchain.CurrentDrawable.texture; color0.loadAction = MTLLoadAction.Load; if (_depthTarget != null) { var depthAttachment = ret.depthAttachment; depthAttachment.texture = _depthTexture.DeviceTexture; depthAttachment.loadAction = MTLLoadAction.Load; } return(ret); }
public void Draw(MTKView view) { inflightSemaphore.WaitOne(); Update(); IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer(); commandBuffer.Label = "Main Command Buffer"; MTLRenderPassDescriptor renderPassDescriptor = view.CurrentRenderPassDescriptor; // Create a render command encoder so we can render into something. IMTLRenderCommandEncoder renderEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor); renderEncoder.Label = "Final Pass Encoder"; renderEncoder.SetViewport(new MTLViewport(0.0, 0.0, view.DrawableSize.Width, view.DrawableSize.Height, 0.0, 1.0)); renderEncoder.SetDepthStencilState(depthState); renderEncoder.SetRenderPipelineState(pipelineState); // Set the our per frame uniforms. renderEncoder.SetVertexBuffer(frameUniformBuffers[constantDataBufferIndex], 0, (nuint)(int)BufferIndex.FrameUniformBuffer); renderEncoder.PushDebugGroup("Render Meshes"); // Render each of our meshes. foreach (MetalKitEssentialsMesh mesh in meshes) { mesh.RenderWithEncoder(renderEncoder); } renderEncoder.PopDebugGroup(); renderEncoder.EndEncoding(); var drawable = view.CurrentDrawable; commandBuffer.AddCompletedHandler(_ => { inflightSemaphore.Release(); drawable.Dispose(); }); constantDataBufferIndex = (constantDataBufferIndex + 1) % maxInflightBuffers; commandBuffer.PresentDrawable(drawable); commandBuffer.Commit(); }
public override void Init(IntPtr display, IntPtr window, uint samples, bool vsync, bool sRGB) { _display = display; _window = window; while (!_dev.SupportsTextureSampleCount(samples)) { samples >>= 1; } _samples = samples; _layer = new CAMetalLayer(); _layer.Device = _dev; _layer.PixelFormat = sRGB ? MTLPixelFormat.BGRA8Unorm_sRGB : MTLPixelFormat.BGRA8Unorm; _layer.FramebufferOnly = true; #if __IOS__ UIView view = (UIView)ObjCRuntime.Runtime.GetNSObject(window); view.Layer.AddSublayer(_layer); #else // Mac NSView view = (NSView)ObjCRuntime.Runtime.GetNSObject(window); view.Layer.AddSublayer(_layer); #endif _cmdQueue = _dev.CreateCommandQueue(); _descriptor = new MTLRenderPassDescriptor(); _descriptor.ColorAttachments[0].ClearColor = new MTLClearColor(0.0, 1.0, 0.0, 0.0); if (samples > 1) { _descriptor.ColorAttachments[0].StoreAction = MTLStoreAction.MultisampleResolve; } else { _descriptor.ColorAttachments[0].StoreAction = MTLStoreAction.Store; } _descriptor.StencilAttachment.ClearStencil = 0; _descriptor.StencilAttachment.LoadAction = MTLLoadAction.Clear; _descriptor.StencilAttachment.StoreAction = MTLStoreAction.DontCare; _device = new Noesis.RenderDeviceMTL(_dev.Handle, sRGB); }
public void Draw(MTKView view) { // Update // Create a new command buffer for each renderpass to the current drawable IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer(); // Call the view's completion handler which is required by the view since it will signal its semaphore and set up the next buffer var drawable = view.CurrentDrawable; // Obtain a renderPassDescriptor generated from the view's drawable textures MTLRenderPassDescriptor renderPassDescriptor = view.CurrentRenderPassDescriptor; // If we have a valid drawable, begin the commands to render into it if (renderPassDescriptor != null) { // Create a render command encoder so we can render into something IMTLRenderCommandEncoder renderEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor); renderEncoder.SetDepthStencilState(depthStencilState); renderEncoder.SetCullMode(MTLCullMode.Front); renderEncoder.SetFrontFacingWinding(MTLWinding.CounterClockwise); renderEncoder.SetTriangleFillMode(MTLTriangleFillMode.Fill); // Set context state renderEncoder.SetRenderPipelineState(pipelineState); renderEncoder.SetVertexBuffer(vertexBuffer, 0, 0); renderEncoder.SetVertexBuffer(instancedBuffer, 0, 1); // Tell the render context we want to draw our primitives renderEncoder.DrawIndexedPrimitives(MTLPrimitiveType.Triangle, (uint)indexData.Length, MTLIndexType.UInt16, indexBuffer, 0, 3); renderEncoder.EndEncoding(); // Schedule a present once the framebuffer is complete using the current drawable commandBuffer.PresentDrawable(drawable); } // Finalize rendering here & push the command buffer to the GPU commandBuffer.Commit(); }
public void Draw(MTKView view) { // Create a new command buffer for each renderpass to the current drawable IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer(); // Call the view's completion handler which is required by the view since it will signal its semaphore and set up the next buffer var drawable = view.CurrentDrawable; // Obtain a renderPassDescriptor generated from the view's drawable textures MTLRenderPassDescriptor renderPassDescriptor = view.CurrentRenderPassDescriptor; // If we have a valid drawable, begin the commands to render into it if (renderPassDescriptor != null) { // Create a render command encoder so we can render into something IMTLRenderCommandEncoder renderEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor); // Set context state renderEncoder.SetDepthStencilState(depthState); renderEncoder.SetRenderPipelineState(pipelineState); renderEncoder.SetVertexBuffer(vertexBuffer, 0, 0); renderEncoder.SetFragmentTexture(this.texture, 0); renderEncoder.SetFragmentSamplerState(this.sampler, 0); // Tell the render context we want to draw our primitives renderEncoder.DrawPrimitives(MTLPrimitiveType.Triangle, 0, (uint)vertexData.Length); // We're done encoding commands renderEncoder.EndEncoding(); // Schedule a present once the framebuffer is complete using the current drawable commandBuffer.PresentDrawable(drawable); } // Finalize rendering here & push the command buffer to the GPU commandBuffer.Commit(); }
public override MTLRenderPassDescriptor CreateRenderPassDescriptor() { MTLRenderPassDescriptor ret = MTLRenderPassDescriptor.New(); for (int i = 0; i < ColorTargets.Count; i++) { FramebufferAttachment colorTarget = ColorTargets[i]; MTLTexture mtlTarget = Util.AssertSubtype <Texture, MTLTexture>(colorTarget.Target); MTLRenderPassColorAttachmentDescriptor colorDescriptor = ret.colorAttachments[(uint)i]; colorDescriptor.texture = mtlTarget.DeviceTexture; colorDescriptor.loadAction = MTLLoadAction.Load; colorDescriptor.slice = (UIntPtr)colorTarget.ArrayLayer; colorDescriptor.level = (UIntPtr)colorTarget.MipLevel; } if (DepthTarget != null) { MTLTexture mtlDepthTarget = Util.AssertSubtype <Texture, MTLTexture>(DepthTarget.Value.Target); MTLRenderPassDepthAttachmentDescriptor depthDescriptor = ret.depthAttachment; depthDescriptor.loadAction = MTLLoadAction.Load; depthDescriptor.storeAction = MTLStoreAction.Store; depthDescriptor.texture = mtlDepthTarget.DeviceTexture; depthDescriptor.slice = (UIntPtr)DepthTarget.Value.ArrayLayer; depthDescriptor.level = (UIntPtr)DepthTarget.Value.MipLevel; if (FormatHelpers.IsStencilFormat(mtlDepthTarget.Format)) { MTLRenderPassStencilAttachmentDescriptor stencilDescriptor = ret.stencilAttachment; stencilDescriptor.loadAction = MTLLoadAction.Load; stencilDescriptor.storeAction = MTLStoreAction.Store; stencilDescriptor.texture = mtlDepthTarget.DeviceTexture; stencilDescriptor.slice = (UIntPtr)DepthTarget.Value.ArrayLayer; } } return(ret); }
private void PlatformConstruct() { DeviceDescriptor = new MTLRenderPassDescriptor(); }
public void Draw(MTKView view) { // Update var time = clock.ElapsedMilliseconds / 1000.0f; var viewProj = Matrix4.Mult(this.view, this.proj); var worldViewProj = Matrix4.CreateRotationX(time) * Matrix4.CreateRotationY(time * 2) * Matrix4.CreateRotationZ(time * .7f) * viewProj; worldViewProj = Matrix4.Transpose(worldViewProj); this.cubeParameters.WorldViewProjection = worldViewProj; this.SetConstantBuffer(this.cubeParameters, this.cubeConstantBuffer); // Create a new command buffer for each renderpass to the current drawable IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer(); // Call the view's completion handler which is required by the view since it will signal its semaphore and set up the next buffer var drawable = view.CurrentDrawable; // Obtain a renderPassDescriptor generated from the view's drawable textures MTLRenderPassDescriptor renderPassDescriptor = view.CurrentRenderPassDescriptor; renderPassDescriptor.ColorAttachments[0].Texture = this.colorFrameBufferTexture; renderPassDescriptor.ColorAttachments[0].ClearColor = new MTLClearColor(0.5f, 0.75f, 1, 1); // If we have a valid drawable, begin the commands to render into it if (renderPassDescriptor != null) { //-------------------------------- // Draw Triangle //-------------------------------- // Create a render command encoder so we can render into something IMTLRenderCommandEncoder triangleRenderEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor); triangleRenderEncoder.SetDepthStencilState(depthStencilState); triangleRenderEncoder.SetRenderPipelineState(trianglePipelineState); triangleRenderEncoder.SetVertexBuffer(triangleVertexBuffer, 0, 0); // Tell the render context we want to draw our primitives triangleRenderEncoder.DrawPrimitives(MTLPrimitiveType.Triangle, 0, (nuint)triangleVertexData.Length); triangleRenderEncoder.EndEncoding(); //-------------------------------- // Draw Cube //-------------------------------- renderPassDescriptor.ColorAttachments[0].Texture = drawable.Texture; renderPassDescriptor.ColorAttachments[0].ClearColor = mtkView.ClearColor; IMTLRenderCommandEncoder cubeRenderEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor); cubeRenderEncoder.SetDepthStencilState(depthStencilState); // Set context state cubeRenderEncoder.SetRenderPipelineState(cubePipelineState); cubeRenderEncoder.SetVertexBuffer(cubeVertexBuffer, 0, 0); cubeRenderEncoder.SetVertexBuffer(cubeConstantBuffer, (nuint)Marshal.SizeOf(this.cubeParameters), 1); cubeRenderEncoder.SetFragmentTexture(this.colorFrameBufferTexture, 0); cubeRenderEncoder.SetFragmentSamplerState(this.sampler, 0); // Tell the render context we want to draw our primitives cubeRenderEncoder.DrawPrimitives(MTLPrimitiveType.Triangle, 0, (nuint)cubeVertexData.Length); // We're done encoding commands cubeRenderEncoder.EndEncoding(); // Schedule a present once the framebuffer is complete using the current drawable commandBuffer.PresentDrawable(drawable); } // Finalize rendering here & push the command buffer to the GPU commandBuffer.Commit(); }
void SetupRenderPassDescriptorForTexture(IMTLTexture texture) { if (renderPassDescriptor == null) { renderPassDescriptor = new MTLRenderPassDescriptor(); } MTLRenderPassColorAttachmentDescriptor colorAttachment = renderPassDescriptor.ColorAttachments [0]; colorAttachment.Texture = texture; colorAttachment.LoadAction = MTLLoadAction.Clear; colorAttachment.ClearColor = new MTLClearColor(0.65f, 0.65f, 0.65f, 1.0f); if (SampleCount > 1) { if (msaaTex == null || NeedUpdate(texture, msaaTex)) { var desc = MTLTextureDescriptor.CreateTexture2DDescriptor(MTLPixelFormat.BGRA8Unorm, texture.Width, texture.Height, false); desc.TextureType = MTLTextureType.k2DMultisample; desc.SampleCount = SampleCount; msaaTex = device.CreateTexture(desc); } colorAttachment.Texture = msaaTex; colorAttachment.ResolveTexture = texture; // set store action to resolve in this case colorAttachment.StoreAction = MTLStoreAction.MultisampleResolve; } else { colorAttachment.StoreAction = MTLStoreAction.Store; } if (DepthPixelFormat != MTLPixelFormat.Invalid) { if (depthTex == null || NeedUpdate(texture, depthTex)) { var desc = MTLTextureDescriptor.CreateTexture2DDescriptor(DepthPixelFormat, texture.Width, texture.Height, false); desc.TextureType = (SampleCount > 1) ? MTLTextureType.k2DMultisample : MTLTextureType.k2D; desc.SampleCount = SampleCount; depthTex = device.CreateTexture(desc); MTLRenderPassDepthAttachmentDescriptor depthAttachment = renderPassDescriptor.DepthAttachment; depthAttachment.Texture = depthTex; depthAttachment.LoadAction = MTLLoadAction.Clear; depthAttachment.StoreAction = MTLStoreAction.DontCare; depthAttachment.ClearDepth = 1.0; } } if (StencilPixelFormat != MTLPixelFormat.Invalid) { if (stencilTex == null || NeedUpdate(texture, stencilTex)) { var desc = MTLTextureDescriptor.CreateTexture2DDescriptor(StencilPixelFormat, texture.Width, texture.Height, false); desc.TextureType = (SampleCount > 1) ? MTLTextureType.k2DMultisample : MTLTextureType.k2D; desc.SampleCount = SampleCount; depthTex = device.CreateTexture(desc); MTLRenderPassStencilAttachmentDescriptor stencilAttachment = renderPassDescriptor.StencilAttachment; stencilAttachment.Texture = depthTex; stencilAttachment.LoadAction = MTLLoadAction.Clear; stencilAttachment.StoreAction = MTLStoreAction.DontCare; stencilAttachment.ClearStencil = 1; } } }
public void Draw(MTKView view) { inflightSemaphore.WaitOne(); // Perofm any app logic, including updating any Metal buffers. Update(); // Create a new command buffer for each renderpass to the current drawable. IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer(); commandBuffer.Label = "Main Command Buffer"; // Obtain a renderPassDescriptor generated from the view's drawable textures. MTLRenderPassDescriptor renderPassDescriptor = view.CurrentRenderPassDescriptor; // Create a render command encoder so we can render into something. IMTLRenderCommandEncoder renderEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor); renderEncoder.Label = "Final Pass Encoder"; // Set context state. renderEncoder.SetViewport(new MTLViewport(0d, 0d, view.DrawableSize.Width, view.DrawableSize.Height, 0d, 1d)); renderEncoder.SetDepthStencilState(depthState); renderEncoder.SetRenderPipelineState(pipelineState); // Set the our per frame uniforms. renderEncoder.SetVertexBuffer(frameUniformBuffers[constantDataBufferIndex], 0, (nuint)(int)BufferIndex.FrameUniformBuffer); renderEncoder.PushDebugGroup("Render Meshes"); // Render each of our meshes. foreach (MetalKitEssentialsMesh mesh in meshes) { mesh.RenderWithEncoder(renderEncoder); } renderEncoder.PopDebugGroup(); // We're done encoding commands. renderEncoder.EndEncoding(); /* * Call the view's completion handler which is required by the view since * it will signal its semaphore and set up the next buffer. */ var drawable = view.CurrentDrawable; commandBuffer.AddCompletedHandler(_ => { inflightSemaphore.Release(); drawable.Dispose(); }); /* * The renderview assumes it can now increment the buffer index and that * the previous index won't be touched until we cycle back around to the same index. */ constantDataBufferIndex = (constantDataBufferIndex + 1) % maxInflightBuffers; // Schedule a present once the framebuffer is complete using the current drawable. commandBuffer.PresentDrawable(drawable); // Finalize rendering here & push the command buffer to the GPU. commandBuffer.Commit(); }
public void Draw(MTKView view) { if (!SDPlugin.IsSDKReady) { return; } // Update sizes if (backgroundTextureSize.Width == 0 && backgroundTextureSize.Height == 0) { var size = MakeBackgroundTextureSize(); backgroundTextureSize = size; UpdateMTKViewFrame(); } // Draw meshes if (SDPlugin.ShowMesh) { MeshController.Update(); } // Get pose and tracking quality var localOrientation = UIApplication.SharedApplication.StatusBarOrientation; float[] mPoseBuffer = new float[16]; int trackingQuality = 0; unsafe { fixed(float *ptr = &mPoseBuffer[0]) { // R T // 0 1 int bufferSize = 16; trackingQuality = SDPlugin.SixDegreesSDK_GetPose(ptr, bufferSize); } } if (trackingQuality > 0) { // Update camera pose var row0 = new SCNVector4(mPoseBuffer[0], mPoseBuffer[1], mPoseBuffer[2], mPoseBuffer[3]); var row1 = new SCNVector4(mPoseBuffer[4], mPoseBuffer[5], mPoseBuffer[6], mPoseBuffer[7]); var row2 = new SCNVector4(mPoseBuffer[8], mPoseBuffer[9], mPoseBuffer[10], mPoseBuffer[11]); var row3 = new SCNVector4(mPoseBuffer[12], mPoseBuffer[13], mPoseBuffer[14], mPoseBuffer[15]); SCNMatrix4 poseMatrix = new SCNMatrix4(row0, row1, row2, row3); CameraNode.WorldTransform = poseMatrix; // Update camera projection var projectionTransform = MakeProjectionMatrix(localOrientation); CameraNode.Camera.ProjectionTransform = projectionTransform; } // Update vertex factory if (vertexFactory.IsComplete == false || orientation != localOrientation) { vertexFactory.Update(localOrientation, backgroundTextureSize); } orientation = localOrientation; // Draw background texture var texturePtr = SDPlugin.SixDegreesSDK_GetBackgroundTexture(); if (texturePtr != IntPtr.Zero) { var obj = ObjCRuntime.Runtime.GetINativeObject <IMTLTexture>(texturePtr, false); Draw((IMTLTexture)obj); } if (commandQueue != null) { var commandBuffer = commandQueue.CommandBuffer(); var currentDrawable = mtkView.CurrentDrawable; double CurrentTime = CAAnimation.CurrentMediaTime(); var screenScale = UIScreen.MainScreen.Scale; var viewport = new CGRect(x: 0, y: 0, width: mtkView.Frame.Width * screenScale, height: mtkView.Frame.Height * screenScale); var renderPassDescriptor = MTLRenderPassDescriptor.CreateRenderPassDescriptor(); renderPassDescriptor.ColorAttachments[0].Texture = currentDrawable.Texture; renderPassDescriptor.ColorAttachments[0].LoadAction = MTLLoadAction.Load; renderPassDescriptor.ColorAttachments[0].StoreAction = MTLStoreAction.Store; renderer.Render(CurrentTime, viewport, commandBuffer, renderPassDescriptor); commandBuffer.PresentDrawable(currentDrawable); commandBuffer.Commit(); } }
private void PlatformConstruct() { DeviceRenderPassDescriptor = AddDisposable(new MTLRenderPassDescriptor()); }
public MTLRenderPassDescriptor GetRenderPassDescriptor (ICAMetalDrawable drawable) { if (drawable == null) { Console.WriteLine ("ERROR: Failed to get a drawable!"); renderPassDescriptor = null; } else { SetupRenderPassDescriptorForTexture (drawable.Texture); } return renderPassDescriptor; }
void SetupRenderPassDescriptorForTexture (IMTLTexture texture) { if (renderPassDescriptor == null) renderPassDescriptor = new MTLRenderPassDescriptor (); MTLRenderPassColorAttachmentDescriptor colorAttachment = renderPassDescriptor.ColorAttachments [0]; colorAttachment.Texture = texture; colorAttachment.LoadAction = MTLLoadAction.Clear; colorAttachment.ClearColor = new MTLClearColor (0.65f, 0.65f, 0.65f, 1.0f); if (SampleCount > 1) { if (msaaTex == null || NeedUpdate (texture, msaaTex)) { var desc = MTLTextureDescriptor.CreateTexture2DDescriptor (MTLPixelFormat.BGRA8Unorm, texture.Width, texture.Height, false); desc.TextureType = MTLTextureType.k2DMultisample; desc.SampleCount = SampleCount; msaaTex = device.CreateTexture (desc); } colorAttachment.Texture = msaaTex; colorAttachment.ResolveTexture = texture; // set store action to resolve in this case colorAttachment.StoreAction = MTLStoreAction.MultisampleResolve; } else { colorAttachment.StoreAction = MTLStoreAction.Store; } if (DepthPixelFormat != MTLPixelFormat.Invalid && (depthTex == null || NeedUpdate (texture, depthTex))) { var desc = MTLTextureDescriptor.CreateTexture2DDescriptor (DepthPixelFormat, texture.Width, texture.Height, false); desc.TextureType = (SampleCount > 1) ? MTLTextureType.k2DMultisample : MTLTextureType.k2D; desc.SampleCount = SampleCount; depthTex = device.CreateTexture (desc); MTLRenderPassDepthAttachmentDescriptor depthAttachment = renderPassDescriptor.DepthAttachment; depthAttachment.Texture = depthTex; depthAttachment.LoadAction = MTLLoadAction.Clear; depthAttachment.StoreAction = MTLStoreAction.DontCare; depthAttachment.ClearDepth = 1.0; } if (StencilPixelFormat != MTLPixelFormat.Invalid && (stencilTex == null || NeedUpdate (texture, stencilTex))) { var desc = MTLTextureDescriptor.CreateTexture2DDescriptor (StencilPixelFormat, texture.Width, texture.Height, false); desc.TextureType = (SampleCount > 1) ? MTLTextureType.k2DMultisample : MTLTextureType.k2D; desc.SampleCount = SampleCount; stencilTex = device.CreateTexture (desc); MTLRenderPassStencilAttachmentDescriptor stencilAttachment = renderPassDescriptor.StencilAttachment; stencilAttachment.Texture = stencilTex; stencilAttachment.LoadAction = MTLLoadAction.Clear; stencilAttachment.StoreAction = MTLStoreAction.DontCare; stencilAttachment.ClearStencil = 0; } }
public void Draw(MTKView view) { // Create a new command buffer for each renderpass to the current drawable IMTLCommandBuffer commandBuffer = commandQueue.CommandBuffer(); // Call the view's completion handler which is required by the view since it will signal its semaphore and set up the next buffer var drawable = view.CurrentDrawable; // Obtain a renderPassDescriptor generated from the view's drawable textures MTLRenderPassDescriptor renderPassDescriptor = view.CurrentRenderPassDescriptor; // If we have a valid drawable, begin the commands to render into it if (renderPassDescriptor != null) { // Create a render command encoder so we can render into something IMTLRenderCommandEncoder renderEncoder = commandBuffer.CreateRenderCommandEncoder(renderPassDescriptor); // First Draw var time = clock.ElapsedMilliseconds / 1000.0f; var viewProj = Matrix4.Mult(this.view, this.proj); var worldViewProj = Matrix4.CreateRotationX(time) * Matrix4.CreateRotationY(time * 2) * Matrix4.CreateRotationZ(time * .7f) * viewProj; param.WorldViewProjection = Matrix4.Transpose(worldViewProj); param.IsTextured = true; SetConstantBuffer(this.param, this.constantBuffer1); // Set context state renderEncoder.SetRenderPipelineState(pipelineState); renderEncoder.SetFrontFacingWinding(MTLWinding.Clockwise); renderEncoder.SetCullMode(MTLCullMode.None); renderEncoder.SetStencilReferenceValue(0); renderEncoder.SetDepthStencilState(depthStencilState1); renderEncoder.SetVertexBuffer(vertexBuffer, 0, 0); renderEncoder.SetFragmentTexture(this.texture, 0); renderEncoder.SetFragmentSamplerState(this.sampler, 0); renderEncoder.SetVertexBuffer(constantBuffer1, (nuint)Marshal.SizeOf(this.param), 1); renderEncoder.SetFragmentBuffer(constantBuffer1, (nuint)Marshal.SizeOf(this.param), 1); // Tell the render context we want to draw our primitives renderEncoder.DrawPrimitives(MTLPrimitiveType.Triangle, 0, (nuint)vertexData.Length); // Second Draw // Set constant buffer param.IsTextured = false; worldViewProj = Matrix4.CreateRotationX(time) * Matrix4.CreateRotationY(time * 2) * Matrix4.CreateRotationZ(time * .7f) * Matrix4.Scale(1.04f) * viewProj; param.WorldViewProjection = Matrix4.Transpose(worldViewProj); SetConstantBuffer(this.param, constantBuffer2); renderEncoder.SetStencilReferenceValue(1); renderEncoder.SetDepthStencilState(depthStencilState2); renderEncoder.SetVertexBuffer(constantBuffer2, (nuint)Marshal.SizeOf(this.param), 1); renderEncoder.SetFragmentBuffer(constantBuffer2, (nuint)Marshal.SizeOf(this.param), 1); // Tell the render context we want to draw our primitives renderEncoder.DrawPrimitives(MTLPrimitiveType.Triangle, 0, (nuint)vertexData.Length); // We're done encoding commands renderEncoder.EndEncoding(); // Schedule a present once the framebuffer is complete using the current drawable commandBuffer.PresentDrawable(drawable); } // Finalize rendering here & push the command buffer to the GPU commandBuffer.Commit(); }
void SetupRenderPassDescriptorForTexture(IMTLTexture texture) { if (renderPassDescriptor == null) renderPassDescriptor = MTLRenderPassDescriptor.CreateRenderPassDescriptor (); renderPassDescriptor.ColorAttachments [0].Texture = texture; renderPassDescriptor.ColorAttachments [0].LoadAction = MTLLoadAction.Clear; renderPassDescriptor.ColorAttachments [0].ClearColor = new MTLClearColor (0.65f, 0.65f, 0.65f, 1.0f); renderPassDescriptor.ColorAttachments [0].StoreAction = MTLStoreAction.Store; if (depthTex == null || (depthTex.Width != texture.Width || depthTex.Height != texture.Height)) { // If we need a depth texture and don't have one, or if the depth texture we have is the wrong size // Then allocate one of the proper size MTLTextureDescriptor desc = MTLTextureDescriptor.CreateTexture2DDescriptor (MTLPixelFormat.Depth32Float, texture.Width, texture.Height, false); depthTex = device.CreateTexture (desc); depthTex.Label = "Depth"; renderPassDescriptor.DepthAttachment.Texture = depthTex; renderPassDescriptor.DepthAttachment.LoadAction = MTLLoadAction.Clear; renderPassDescriptor.DepthAttachment.ClearDepth = 1.0f; renderPassDescriptor.DepthAttachment.StoreAction = MTLStoreAction.DontCare; } }