diff options
| author | skallweitNV <64953474+skallweitNV@users.noreply.github.com> | 2024-06-10 18:12:01 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-10 18:12:01 +0200 |
| commit | 6857dd57549f01daa025f45221a693259e474958 (patch) | |
| tree | c6db90150ff093eea525e57c7e52c0cc1c970095 /tools | |
| parent | 0974463daf0982626cb2b8c8bb6f494f3e6c9e52 (diff) | |
[gfx] Metal graphics support (#4324)
* fix double semicolons
* fix another double semicolon
* wait for init data upload
* remove obsolete setData
* refactor swapchain to work on virtual back buffers
* buffer/texture use breakable device reference
* refactor input layout
* create render command encoder
* add todo
* refactor framebuffer layout
* refactor framebuffer
* refactor shader program
* translatePrimitiveType
* add more translate functions
* refactor framebuffer
* refactor render pass
* implement graphics pipeline state
* add depth stencil state
* initial render command encoder support
* comment
Diffstat (limited to 'tools')
23 files changed, 748 insertions, 367 deletions
diff --git a/tools/gfx/metal/metal-buffer.h b/tools/gfx/metal/metal-buffer.h index 08fa6481d..3f8f60d0e 100644 --- a/tools/gfx/metal/metal-buffer.h +++ b/tools/gfx/metal/metal-buffer.h @@ -17,7 +17,7 @@ class BufferResourceImpl : public BufferResource public: typedef BufferResource Parent; - RefPtr<DeviceImpl> m_device; + BreakableReference<DeviceImpl> m_device; NS::SharedPtr<MTL::Buffer> m_buffer; BufferResourceImpl(const IBufferResource::Desc& desc, DeviceImpl* device); diff --git a/tools/gfx/metal/metal-command-buffer.cpp b/tools/gfx/metal/metal-command-buffer.cpp index 8aac6ea4b..c54552ae4 100644 --- a/tools/gfx/metal/metal-command-buffer.cpp +++ b/tools/gfx/metal/metal-command-buffer.cpp @@ -80,12 +80,12 @@ Result CommandBufferImpl::getNativeHandle(InteropHandle* outHandle) return SLANG_E_NOT_IMPLEMENTED; } -MTL::RenderCommandEncoder* CommandBufferImpl::getMetalRenderCommandEncoder() +MTL::RenderCommandEncoder* CommandBufferImpl::getMetalRenderCommandEncoder(MTL::RenderPassDescriptor* renderPassDesc) { if (!m_metalRenderCommandEncoder) { endMetalCommandEncoder(); - // m_metalRenderCommandEncoder = NS::RetainPtr(m_commandBuffer->renderCommandEncoder()); + m_metalRenderCommandEncoder = NS::RetainPtr(m_commandBuffer->renderCommandEncoder(renderPassDesc)); } return m_metalRenderCommandEncoder.get(); } diff --git a/tools/gfx/metal/metal-command-buffer.h b/tools/gfx/metal/metal-command-buffer.h index 3041ba310..6c000b5df 100644 --- a/tools/gfx/metal/metal-command-buffer.h +++ b/tools/gfx/metal/metal-command-buffer.h @@ -45,7 +45,7 @@ public: void beginCommandBuffer(); - MTL::RenderCommandEncoder* getMetalRenderCommandEncoder(); + MTL::RenderCommandEncoder* getMetalRenderCommandEncoder(MTL::RenderPassDescriptor* renderPassDesc); MTL::ComputeCommandEncoder* getMetalComputeCommandEncoder(); MTL::BlitCommandEncoder* getMetalBlitCommandEncoder(); void endMetalCommandEncoder(); diff --git a/tools/gfx/metal/metal-command-encoder.cpp b/tools/gfx/metal/metal-command-encoder.cpp index f1e834400..3e0fbd1f6 100644 --- a/tools/gfx/metal/metal-command-encoder.cpp +++ b/tools/gfx/metal/metal-command-encoder.cpp @@ -209,52 +209,59 @@ void ResourceCommandEncoder::endDebugEvent() void RenderCommandEncoder::beginPass(IRenderPassLayout* renderPass, IFramebuffer* framebuffer) { - FramebufferImpl* fb = static_cast<FramebufferImpl*>(framebuffer); - if (fb == nullptr) + m_renderPassLayout = static_cast<RenderPassLayoutImpl*>(renderPass); + m_framebuffer = static_cast<FramebufferImpl*>(framebuffer); + if (!m_framebuffer) { + // TODO use empty framebuffer return; } - RenderPassLayoutImpl* renderPassLayoutImpl = static_cast<RenderPassLayoutImpl*>(renderPass); - MTL::RenderPassDescriptor* rpd = renderPassLayoutImpl->m_renderPassDesc->copy(); + // Create a copy of the render pass descriptor and fill in remaining information. + m_renderPassDesc = NS::TransferPtr(m_renderPassLayout->m_renderPassDesc->copy()); - if (rpd->depthAttachment() && false) + m_renderPassDesc->setRenderTargetWidth(m_framebuffer->m_width); + m_renderPassDesc->setRenderTargetHeight(m_framebuffer->m_height); + + for (Index i = 0; i < m_framebuffer->m_renderTargetViews.getCount(); ++i) { - TextureResourceViewImpl* depthView = static_cast<TextureResourceViewImpl*>(fb->depthStencilView.get()); - rpd->depthAttachment()->setTexture(depthView->m_texture->m_texture.get()); + TextureResourceViewImpl* renderTargetView = m_framebuffer->m_renderTargetViews[i]; + MTL::RenderPassColorAttachmentDescriptor* colorAttachment = m_renderPassDesc->colorAttachments()->object(i); + colorAttachment->setTexture(renderTargetView->m_texture->m_texture.get()); + colorAttachment->setLevel(renderTargetView->m_desc.subresourceRange.mipLevel); + colorAttachment->setSlice(renderTargetView->m_desc.subresourceRange.baseArrayLayer); } - const int colorTargetCount = fb->renderTargetViews.getCount(); - for (int i = 0; i < colorTargetCount; ++i) + + if (m_framebuffer->m_depthStencilView) { - TextureResourceViewImpl* texView = static_cast<TextureResourceViewImpl*>(fb->renderTargetViews[i].get()); - MTL::Texture* tex = nullptr; - assert(texView->m_texture); - tex = texView->m_texture->m_texture.get(); - rpd->colorAttachments()->object(i)->setTexture(tex); - rpd->colorAttachments()->object(i)->setClearColor(MTL::ClearColor(0.2, 0.4, 0.9, 1.0)); + TextureResourceViewImpl* depthStencilView = m_framebuffer->m_depthStencilView.get(); + MTL::PixelFormat pixelFormat = MetalUtil::translatePixelFormat(depthStencilView->m_desc.format); + if (MetalUtil::isDepthFormat(pixelFormat)) + { + MTL::RenderPassDepthAttachmentDescriptor* depthAttachment = m_renderPassDesc->depthAttachment(); + depthAttachment->setTexture(depthStencilView->m_texture->m_texture.get()); + depthAttachment->setLevel(depthStencilView->m_desc.subresourceRange.mipLevel); + depthAttachment->setSlice(depthStencilView->m_desc.subresourceRange.baseArrayLayer); + } + if (MetalUtil::isStencilFormat(pixelFormat)) + { + MTL::RenderPassStencilAttachmentDescriptor* stencilAttachment = m_renderPassDesc->stencilAttachment(); + stencilAttachment->setTexture(depthStencilView->m_texture->m_texture.get()); + stencilAttachment->setLevel(depthStencilView->m_desc.subresourceRange.mipLevel); + stencilAttachment->setSlice(depthStencilView->m_desc.subresourceRange.baseArrayLayer); + } } - rpd->setRenderTargetWidth(fb->m_width); - rpd->setRenderTargetHeight(fb->m_height); - - m_encoder = m_metalCommandBuffer->renderCommandEncoder(rpd); } void RenderCommandEncoder::endEncoding() { - m_encoder->endEncoding(); + PipelineCommandEncoder::endEncodingImpl(); } Result RenderCommandEncoder::bindPipeline( IPipelineState* pipelineState, IShaderObject** outRootObject) { - m_currentPipeline = static_cast<PipelineStateImpl*>(pipelineState); - // Initialize the root object - SLANG_RETURN_ON_FAIL(m_commandBuffer->m_rootObject.init(m_commandBuffer->m_device, - m_currentPipeline->getProgram<ShaderProgramImpl>()->m_rootObjectLayout)); - *outRootObject = &m_commandBuffer->m_rootObject; - //if (pPipelineState->m_renderState == nullptr) return SLANG_ERROR_INVALID_PARAMETER; - //m_encoder->setRenderPipelineState(pPipelineState->m_renderState); - return SLANG_OK; + return setPipelineStateImpl(pipelineState, outRootObject); } Result RenderCommandEncoder::bindPipelineWithRootObject( @@ -265,44 +272,37 @@ Result RenderCommandEncoder::bindPipelineWithRootObject( void RenderCommandEncoder::setViewports(GfxCount count, const Viewport* viewports) { - static const int kMaxViewports = 8; // TODO: base on device caps - assert(count <= kMaxViewports); - m_viewports.setCount(count); for (GfxIndex i = 0; i < count; ++i) { - const auto& inViewport = viewports[i]; - auto& metalViewport = m_viewports[i]; - metalViewport.height = inViewport.extentY; - metalViewport.width = inViewport.extentX; - metalViewport.originX = inViewport.originX; - metalViewport.originY = inViewport.originY; - metalViewport.znear = inViewport.minZ; - metalViewport.zfar = inViewport.maxZ; + const auto& viewport = viewports[i]; + auto& mtlViewport = m_viewports[i]; + mtlViewport.originX = viewport.originX; + mtlViewport.originY = viewport.originY; + mtlViewport.width = viewport.extentX; + mtlViewport.height = viewport.extentY; + mtlViewport.znear = viewport.minZ; + mtlViewport.zfar = viewport.maxZ; } - m_encoder->setViewports(m_viewports.begin(), count); } void RenderCommandEncoder::setScissorRects(GfxCount count, const ScissorRect* rects) { - static const int kMaxScissorRects = 9; // TODO: - assert(count < kMaxScissorRects); - m_scissorRects.setCount(count); for (GfxIndex i = 0; i < count; ++i) { - const auto& inRect = rects[i]; - auto& metalRect = m_scissorRects[i]; - metalRect.height = inRect.maxX - inRect.minX; - metalRect.width = inRect.maxY - inRect.minY; - metalRect.x = inRect.minX; - metalRect.y = inRect.minY; + const auto& rect = rects[i]; + auto& mtlRect = m_scissorRects[i]; + mtlRect.x = rect.minX; + mtlRect.y = rect.minY; + mtlRect.width = rect.maxX - rect.minX; + mtlRect.height = rect.maxY - rect.minY; } - m_encoder->setScissorRects(m_scissorRects.begin(), count); } void RenderCommandEncoder::setPrimitiveTopology(PrimitiveTopology topology) { + m_primitiveType = MetalUtil::translatePrimitiveType(topology); } void RenderCommandEncoder::setVertexBuffers( @@ -311,79 +311,104 @@ void RenderCommandEncoder::setVertexBuffers( IBufferResource* const* buffers, const Offset* offsets) { - for (GfxIndex i = 0; i < GfxIndex(slotCount); i++) + Index count = Math::Max(m_vertexBuffers.getCount(), Index(startSlot + slotCount)); + m_vertexBuffers.setCount(count); + m_vertexBufferOffsets.setCount(count); + + for (Index i = 0; i < Index(slotCount); i++) { - GfxIndex slotIndex = startSlot + i; - BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[i]); - if (buffer) - { - MTL::Buffer* vertexBuffers = {buffer->m_buffer.get()}; - m_encoder->setVertexBuffer(buffer->m_buffer.get(), offsets[i], slotIndex); - // ... - } + Index slotIndex = startSlot + i; + m_vertexBuffers[slotIndex] = static_cast<BufferResourceImpl*>(buffers[i])->m_buffer.get(); + m_vertexBufferOffsets[slotIndex] = offsets[i]; } } void RenderCommandEncoder::setIndexBuffer( IBufferResource* buffer, Format indexFormat, Offset offset) { + m_indexBuffer = static_cast<BufferResourceImpl*>(buffer)->m_buffer.get(); + m_indexBufferOffset = offset; + + switch (indexFormat) + { + case Format::R16_UINT: + m_indexBufferType = MTL::IndexTypeUInt16; + break; + case Format::R32_UINT: + m_indexBufferType = MTL::IndexTypeUInt32; + break; + default: + assert(!"unsupported index format"); + } +} + +void RenderCommandEncoder::setStencilReference(uint32_t referenceValue) +{ + m_stencilReferenceValue = referenceValue; } -Result RenderCommandEncoder::prepareDraw() +Result RenderCommandEncoder::setSamplePositions( + GfxCount samplesPerPixel, GfxCount pixelCount, const SamplePosition* samplePositions) +{ + return SLANG_E_NOT_AVAILABLE; +} + +Result RenderCommandEncoder::prepareDraw(MTL::RenderCommandEncoder*& encoder) { - // Bind render state, including JIT pipeline state object creation auto pipeline = static_cast<PipelineStateImpl*>(m_currentPipeline.Ptr()); - if (!pipeline) + pipeline->ensureAPIPipelineStateCreated(); + + encoder = m_commandBuffer->getMetalRenderCommandEncoder(m_renderPassDesc.get()); + encoder->setRenderPipelineState(pipeline->m_renderPipelineState.get()); + // TODO only vertex stage bindings are set for now + VertexBindingContext bindingContext; + bindingContext.init(m_commandBuffer->m_device, encoder); + auto program = static_cast<ShaderProgramImpl*>(m_currentPipeline->m_program.get()); + m_commandBuffer->m_rootObject.bindAsRoot(&bindingContext, program->m_rootObjectLayout); + + for (Index i = 0; i < m_vertexBuffers.getCount(); ++i) { - return SLANG_FAIL; + encoder->setVertexBuffer(m_vertexBuffers[i], m_vertexBufferOffsets[i], m_currentPipeline->m_vertexBufferOffset + i); } - // TODO: specialization, binding, ... - SLANG_RETURN_ON_FAIL(pipeline->ensureAPIPipelineStateCreated()); - return SLANG_OK; -} -static Result translatePrimitiveType(gfx::PrimitiveType primType, MTL::PrimitiveType& mtlType) -{ - switch (primType) + encoder->setViewports(m_viewports.getArrayView().getBuffer(), m_viewports.getCount()); + encoder->setScissorRects(m_scissorRects.getArrayView().getBuffer(), m_scissorRects.getCount()); + + const RasterizerDesc& rasterDesc = pipeline->desc.graphics.rasterizer; + const DepthStencilDesc& depthStencilDesc = pipeline->desc.graphics.depthStencil; + encoder->setFrontFacingWinding(MetalUtil::translateWinding(rasterDesc.frontFace)); + encoder->setCullMode(MetalUtil::translateCullMode(rasterDesc.cullMode)); + encoder->setDepthClipMode(rasterDesc.depthClipEnable ? MTL::DepthClipModeClip : MTL::DepthClipModeClamp); // TODO correct? + encoder->setDepthBias(rasterDesc.depthBias, rasterDesc.slopeScaledDepthBias, rasterDesc.depthBiasClamp); + encoder->setTriangleFillMode(MetalUtil::translateTriangleFillMode(rasterDesc.fillMode)); + // encoder->setBlendColor(); // not supported by gfx + if (m_framebuffer->m_depthStencilView) { - case PrimitiveType::Triangle: - mtlType = MTL::PrimitiveTypeTriangle; - break; - case PrimitiveType::Line: - mtlType = MTL::PrimitiveTypeLine; - break; - case PrimitiveType::Point: - mtlType = MTL::PrimitiveTypePoint; - break; - case PrimitiveType::Patch: - default: - return SLANG_E_INVALID_ARG; + encoder->setDepthStencilState(pipeline->m_depthStencilState.get()); } + encoder->setStencilReferenceValue(m_stencilReferenceValue); + return SLANG_OK; } Result RenderCommandEncoder::draw(GfxCount vertexCount, GfxIndex startVertex) { - SLANG_RETURN_ON_FAIL(prepareDraw()); - - MTL::PrimitiveType primType; - Result res = translatePrimitiveType(m_currentPipeline->desc.graphics.primitiveType, primType); - if (res != SLANG_OK) - return res; - m_encoder->drawPrimitives(primType, startVertex, vertexCount); + MTL::RenderCommandEncoder* encoder; + SLANG_RETURN_ON_FAIL(prepareDraw(encoder)); + encoder->drawPrimitives(m_primitiveType, startVertex, vertexCount); return SLANG_OK; } Result RenderCommandEncoder::drawIndexed( GfxCount indexCount, GfxIndex startIndex, GfxIndex baseVertex) { + MTL::RenderCommandEncoder* encoder; + SLANG_RETURN_ON_FAIL(prepareDraw(encoder)); + // TODO baseVertex is not supported by Metal + encoder->drawIndexedPrimitives(m_primitiveType, indexCount, m_indexBufferType, m_indexBuffer, m_indexBufferOffset); return SLANG_E_NOT_IMPLEMENTED; } -void RenderCommandEncoder::setStencilReference(uint32_t referenceValue) -{ -} - Result RenderCommandEncoder::drawIndirect( GfxCount maxDrawCount, IBufferResource* argBuffer, @@ -404,20 +429,16 @@ Result RenderCommandEncoder::drawIndexedIndirect( return SLANG_E_NOT_IMPLEMENTED; } -Result RenderCommandEncoder::setSamplePositions( - GfxCount samplesPerPixel, GfxCount pixelCount, const SamplePosition* samplePositions) -{ - return SLANG_E_NOT_AVAILABLE; -} - Result RenderCommandEncoder::drawInstanced( GfxCount vertexCount, GfxCount instanceCount, GfxIndex startVertex, GfxIndex startInstanceLocation) { - SLANG_RETURN_ON_FAIL(prepareDraw()); - return SLANG_E_NOT_IMPLEMENTED; + MTL::RenderCommandEncoder* encoder; + SLANG_RETURN_ON_FAIL(prepareDraw(encoder)); + encoder->drawPrimitives(m_primitiveType, startVertex, vertexCount, instanceCount, startInstanceLocation); + return SLANG_OK; } Result RenderCommandEncoder::drawIndexedInstanced( @@ -427,13 +448,14 @@ Result RenderCommandEncoder::drawIndexedInstanced( GfxIndex baseVertexLocation, GfxIndex startInstanceLocation) { - SLANG_RETURN_ON_FAIL(prepareDraw()); - return SLANG_E_NOT_IMPLEMENTED; + MTL::RenderCommandEncoder* encoder; + SLANG_RETURN_ON_FAIL(prepareDraw(encoder)); + encoder->drawIndexedPrimitives(m_primitiveType, indexCount, m_indexBufferType, m_indexBuffer, startIndexLocation, instanceCount, baseVertexLocation, startIndexLocation); + return SLANG_OK; } Result RenderCommandEncoder::drawMeshTasks(int x, int y, int z) { - SLANG_RETURN_ON_FAIL(prepareDraw()); return SLANG_E_NOT_IMPLEMENTED; } @@ -459,16 +481,15 @@ Result ComputeCommandEncoder::dispatchCompute(int x, int y, int z) auto pipeline = static_cast<PipelineStateImpl*>(m_currentPipeline.Ptr()); pipeline->ensureAPIPipelineStateCreated(); - auto metalComputeCommandEncoder = m_commandBuffer->getMetalComputeCommandEncoder(); - metalComputeCommandEncoder->setComputePipelineState(pipeline->m_computePipelineState.get()); + MTL::ComputeCommandEncoder* encoder = m_commandBuffer->getMetalComputeCommandEncoder(); + encoder->setComputePipelineState(pipeline->m_computePipelineState.get()); ComputeBindingContext bindingContext; - bindingContext.init(m_commandBuffer->m_device, metalComputeCommandEncoder); + bindingContext.init(m_commandBuffer->m_device, encoder); auto program = static_cast<ShaderProgramImpl*>(m_currentPipeline->m_program.get()); m_commandBuffer->m_rootObject.bindAsRoot(&bindingContext, program->m_rootObjectLayout); - metalComputeCommandEncoder->dispatchThreadgroups(MTL::Size(x, y, z), pipeline->m_threadGroupSize); + encoder->dispatchThreadgroups(MTL::Size(x, y, z), pipeline->m_threadGroupSize); - // Also create descriptor sets based on the given pipeline layout - return SLANG_E_NOT_IMPLEMENTED; + return SLANG_OK; } Result ComputeCommandEncoder::dispatchComputeIndirect(IBufferResource* argBuffer, Offset offset) diff --git a/tools/gfx/metal/metal-command-encoder.h b/tools/gfx/metal/metal-command-encoder.h index 851ee60af..8ef9e5fb5 100644 --- a/tools/gfx/metal/metal-command-encoder.h +++ b/tools/gfx/metal/metal-command-encoder.h @@ -3,6 +3,7 @@ #include "metal-base.h" #include "metal-pipeline-state.h" +#include "metal-render-pass.h" namespace gfx { @@ -159,9 +160,22 @@ class RenderCommandEncoder return nullptr; } public: - MTL::RenderCommandEncoder* m_encoder; - List<MTL::ScissorRect> m_scissorRects; - List<MTL::Viewport> m_viewports; + RefPtr<RenderPassLayoutImpl> m_renderPassLayout; + RefPtr<FramebufferImpl> m_framebuffer; + NS::SharedPtr<MTL::RenderPassDescriptor> m_renderPassDesc; + + ShortList<MTL::Viewport, 16> m_viewports; + ShortList<MTL::ScissorRect, 16> m_scissorRects; + MTL::PrimitiveType m_primitiveType = MTL::PrimitiveTypeTriangle; + + ShortList<MTL::Buffer*, 16> m_vertexBuffers; + ShortList<NS::UInteger, 16> m_vertexBufferOffsets; + + MTL::Buffer* m_indexBuffer = nullptr; + NS::UInteger m_indexBufferOffset = 0; + MTL::IndexType m_indexBufferType = MTL::IndexTypeUInt16; + + uint32_t m_stencilReferenceValue = 0; public: void beginPass(IRenderPassLayout* renderPass, IFramebuffer* framebuffer); @@ -192,15 +206,20 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL setIndexBuffer(IBufferResource* buffer, Format indexFormat, Offset offset = 0) override; - Result prepareDraw(); + virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) override; + + virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( + GfxCount samplesPerPixel, + GfxCount pixelCount, + const SamplePosition* samplePositions) override; + + Result prepareDraw(MTL::RenderCommandEncoder*& encoder); virtual SLANG_NO_THROW Result SLANG_MCALL draw(GfxCount vertexCount, GfxIndex startVertex = 0) override; virtual SLANG_NO_THROW Result SLANG_MCALL drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0) override; - virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) override; - virtual SLANG_NO_THROW Result SLANG_MCALL drawIndirect( GfxCount maxDrawCount, IBufferResource* argBuffer, @@ -215,11 +234,6 @@ public: IBufferResource* countBuffer, Offset countOffset) override; - virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( - GfxCount samplesPerPixel, - GfxCount pixelCount, - const SamplePosition* samplePositions) override; - virtual SLANG_NO_THROW Result SLANG_MCALL drawInstanced( GfxCount vertexCount, GfxCount instanceCount, diff --git a/tools/gfx/metal/metal-device.cpp b/tools/gfx/metal/metal-device.cpp index d844e6e89..a4cf23da3 100644 --- a/tools/gfx/metal/metal-device.cpp +++ b/tools/gfx/metal/metal-device.cpp @@ -144,9 +144,9 @@ Result DeviceImpl::createSwapchain( { AUTORELEASEPOOL - RefPtr<SwapchainImpl> sc = new SwapchainImpl(); - SLANG_RETURN_ON_FAIL(sc->init(this, desc, window)); - returnComPtr(outSwapchain, sc); + RefPtr<SwapchainImpl> swapchainImpl = new SwapchainImpl(); + SLANG_RETURN_ON_FAIL(swapchainImpl->init(this, desc, window)); + returnComPtr(outSwapchain, swapchainImpl); return SLANG_OK; } @@ -154,9 +154,9 @@ Result DeviceImpl::createFramebufferLayout(const IFramebufferLayout::Desc& desc, { AUTORELEASEPOOL - RefPtr<FramebufferLayoutImpl> layout = new FramebufferLayoutImpl; - SLANG_RETURN_ON_FAIL(layout->init(this, desc)); - returnComPtr(outLayout, layout); + RefPtr<FramebufferLayoutImpl> layoutImpl = new FramebufferLayoutImpl; + SLANG_RETURN_ON_FAIL(layoutImpl->init(desc)); + returnComPtr(outLayout, layoutImpl); return SLANG_OK; } @@ -164,9 +164,9 @@ Result DeviceImpl::createRenderPassLayout(const IRenderPassLayout::Desc& desc, I { AUTORELEASEPOOL - RefPtr<RenderPassLayoutImpl> result = new RenderPassLayoutImpl; - SLANG_RETURN_ON_FAIL(result->init(this, desc)); - returnComPtr(outRenderPassLayout, result); + RefPtr<RenderPassLayoutImpl> renderPassLayoutImpl = new RenderPassLayoutImpl; + SLANG_RETURN_ON_FAIL(renderPassLayoutImpl->init(this, desc)); + returnComPtr(outRenderPassLayout, renderPassLayoutImpl); return SLANG_OK; } @@ -174,9 +174,9 @@ Result DeviceImpl::createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffe { AUTORELEASEPOOL - RefPtr<FramebufferImpl> fb = new FramebufferImpl; - SLANG_RETURN_ON_FAIL(fb->init(this, desc)); - returnComPtr(outFramebuffer, fb); + RefPtr<FramebufferImpl> framebufferImpl = new FramebufferImpl; + SLANG_RETURN_ON_FAIL(framebufferImpl->init(this, desc)); + returnComPtr(outFramebuffer, framebufferImpl); return SLANG_OK; } @@ -381,6 +381,8 @@ Result DeviceImpl::createTextureResource( return SLANG_FAIL; } + // TODO: handle initData + returnComPtr(outResource, textureImpl); return SLANG_OK; } @@ -429,6 +431,7 @@ Result DeviceImpl::createBufferResource( encoder->copyFromBuffer(stagingBuffer.get(), 0, bufferImpl->m_buffer.get(), 0, bufferSize); encoder->endEncoding(); commandBuffer->commit(); + commandBuffer->waitUntilCompleted(); } returnComPtr(outResource, bufferImpl); @@ -558,8 +561,8 @@ Result DeviceImpl::createBufferView( RefPtr<BufferResourceViewImpl> viewImpl = new BufferResourceViewImpl(this); viewImpl->m_desc = desc; viewImpl->m_buffer = bufferImpl; - viewImpl->m_offset = desc.bufferRange.offset;; - viewImpl->m_size = desc.bufferRange.size == 0 ? bufferImpl->getDesc()->sizeInBytes : desc.bufferRange.size;; + viewImpl->m_offset = desc.bufferRange.offset; + viewImpl->m_size = desc.bufferRange.size == 0 ? bufferImpl->getDesc()->sizeInBytes : desc.bufferRange.size; returnComPtr(outView, viewImpl); return SLANG_OK; } @@ -568,37 +571,9 @@ Result DeviceImpl::createInputLayout(IInputLayout::Desc const& desc, IInputLayou { AUTORELEASEPOOL - RefPtr<InputLayoutImpl> layout(new InputLayoutImpl); - layout->m_vertexDescriptor = NS::TransferPtr(MTL::VertexDescriptor::alloc()->init()); - if (!layout->m_vertexDescriptor) - { - return SLANG_FAIL; - } - - for (Int i = 0; i < desc.inputElementCount; ++i) - { - const auto& inputElement = desc.inputElements[i]; - MTL::VertexAttributeDescriptor* desc = layout->m_vertexDescriptor->attributes()->object(i); - desc->setOffset(inputElement.offset); - desc->setBufferIndex(inputElement.bufferSlotIndex); - MTL::VertexFormat metalFormat = MetalUtil::translateVertexFormat(inputElement.format); - if (metalFormat == MTL::VertexFormatInvalid) - { - return SLANG_FAIL; - } - desc->setFormat(metalFormat); - } - - for (Int i = 0; i < desc.vertexStreamCount; ++i) - { - const auto& vertexStream = desc.vertexStreams[i]; - MTL::VertexBufferLayoutDescriptor* desc = layout->m_vertexDescriptor->layouts()->object(i); - desc->setStepFunction(MetalUtil::translateVertexStepFunction(vertexStream.slotClass)); - desc->setStepRate(vertexStream.instanceDataStepRate); - desc->setStride(vertexStream.stride); - } - - returnComPtr(outLayout, layout); + RefPtr<InputLayoutImpl> layoutImpl(new InputLayoutImpl); + SLANG_RETURN_ON_FAIL(layoutImpl->init(desc)); + returnComPtr(outLayout, layoutImpl); return SLANG_OK; } diff --git a/tools/gfx/metal/metal-framebuffer.cpp b/tools/gfx/metal/metal-framebuffer.cpp index 46e60b2eb..76e944b4a 100644 --- a/tools/gfx/metal/metal-framebuffer.cpp +++ b/tools/gfx/metal/metal-framebuffer.cpp @@ -12,60 +12,56 @@ using namespace Slang; namespace metal { -FramebufferLayoutImpl::~FramebufferLayoutImpl() +Result FramebufferLayoutImpl::init(const IFramebufferLayout::Desc& desc) { - //m_renderPass->release(); -} - -Result FramebufferLayoutImpl::init(DeviceImpl* device, const IFramebufferLayout::Desc& desc) -{ - // Metal doesn't have a notion of Framebuffers or FramebufferLayouts per se. - // We simply stash the desc and use it when creating the (convenience) Framebuffer - m_device = device; - m_desc = desc; + for (Index i = 0; i < desc.renderTargetCount; ++i) + { + m_renderTargets.add(desc.renderTargets[i]); + } + if (desc.depthStencil) + { + m_depthStencil = *desc.depthStencil; + } + else + { + m_depthStencil = {}; + } return SLANG_OK; } -FramebufferImpl::~FramebufferImpl() -{ -} - Result FramebufferImpl::init(DeviceImpl* device, const IFramebuffer::Desc& desc) { m_device = device; m_layout = static_cast<FramebufferLayoutImpl*>(desc.layout); - m_width = m_height = 1; - - TextureResourceViewImpl* dsv = static_cast<TextureResourceViewImpl*>(desc.depthStencilView); - - // Get frame dimensions from attachments. - if (dsv) + m_renderTargetViews.setCount(desc.renderTargetCount); + for (Index i = 0; i < desc.renderTargetCount; ++i) { - // If we have a depth attachment, get frame size from there. - auto size = dsv->m_texture->getDesc()->size; - auto viewDesc = dsv->getViewDesc(); - m_width = Math::Max(1u, uint32_t(size.width >> viewDesc->subresourceRange.mipLevel)); - m_height = Math::Max(1u, uint32_t(size.height >> viewDesc->subresourceRange.mipLevel)); - } - else if (desc.renderTargetCount > 0) - { - // If we don't have a depth attachment, then we must have at least - // one color attachment. Get frame dimension from there. - auto viewImpl = static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[0]); - auto resourceDesc = viewImpl->m_texture->getDesc(); - auto viewDesc = viewImpl->getViewDesc(); - auto size = resourceDesc->size; - m_width = Math::Max(1u, uint32_t(size.width >> viewDesc->subresourceRange.mipLevel)); - m_height = Math::Max(1u, uint32_t(size.height >> viewDesc->subresourceRange.mipLevel)); + m_renderTargetViews[i] = static_cast<TextureResourceViewImpl*>(desc.renderTargetViews[i]); } + m_depthStencilView = static_cast<TextureResourceViewImpl*>(desc.depthStencilView); + + // Determine framebuffer dimensions & sample count; + m_width = 1; + m_height = 1; + m_sampleCount = 1; - // Initialize depthstencil and render target views - depthStencilView = desc.depthStencilView; + auto visitView = [this](TextureResourceViewImpl* view) + { + const ITextureResource::Desc* textureDesc = view->m_texture->getDesc(); + const IResourceView::Desc* viewDesc = view->getViewDesc(); + m_width = Math::Max(1u, uint32_t(textureDesc->size.width >> viewDesc->subresourceRange.mipLevel)); + m_height = Math::Max(1u, uint32_t(textureDesc->size.height >> viewDesc->subresourceRange.mipLevel)); + m_sampleCount = Math::Max(m_sampleCount, uint32_t(textureDesc->sampleDesc.numSamples)); + return SLANG_OK; + }; - renderTargetViews.setCount(desc.renderTargetCount); - for (int i = 0; i < desc.renderTargetCount; ++i) + for (auto view : m_renderTargetViews) + { + visitView(view); + } + if (m_depthStencilView) { - renderTargetViews[i] = desc.renderTargetViews[i]; + visitView(m_depthStencilView); } return SLANG_OK; diff --git a/tools/gfx/metal/metal-framebuffer.h b/tools/gfx/metal/metal-framebuffer.h index 7bd3b0bef..90abf1b85 100644 --- a/tools/gfx/metal/metal-framebuffer.h +++ b/tools/gfx/metal/metal-framebuffer.h @@ -20,41 +20,25 @@ enum class FramebufferLayoutImpl : public FramebufferLayoutBase { public: - RefPtr<DeviceImpl> m_device; - Desc m_desc; -#if 0 - MTL::RenderPassDescriptor* m_renderPass = nullptr; - Array<MTL::RenderPassColorAttachmentDescriptor*, kMaxTargets> m_targetDescs; - MTL::RenderPassDepthAttachmentDescriptor* m_depthAttachmentDesc = nullptr; - MTL::RenderPassStencilAttachmentDescriptor* m_stencilAttachmentDesc = nullptr; - bool m_hasDepthStencilTarget = false; - uint32_t m_renderTargetCount = 0; -#endif + List<IFramebufferLayout::TargetLayout> m_renderTargets; + IFramebufferLayout::TargetLayout m_depthStencil; public: - ~FramebufferLayoutImpl(); - Result init(DeviceImpl* device, const IFramebufferLayout::Desc& desc); + Result init(const IFramebufferLayout::Desc& desc); }; class FramebufferImpl : public FramebufferBase { public: BreakableReference<DeviceImpl> m_device; - ShortList<ComPtr<IResourceView>> renderTargetViews; - ComPtr<IResourceView> depthStencilView; + RefPtr<FramebufferLayoutImpl> m_layout; + ShortList<RefPtr<TextureResourceViewImpl>> m_renderTargetViews; + RefPtr<TextureResourceViewImpl> m_depthStencilView; uint32_t m_width; uint32_t m_height; - MTL::ClearColor m_clearValues[kMaxTargets]; - RefPtr<FramebufferLayoutImpl> m_layout; -#if 0 - Array<MTL::RenderPassColorAttachmentDescriptor*, kMaxTargets> m_colorTargetDescs; - MTL::RenderPassDepthAttachmentDescriptor* m_depthAttachmentDesc = nullptr; - MTL::RenderPassStencilAttachmentDescriptor* m_stencilAttachmentDesc = nullptr; -#endif + uint32_t m_sampleCount; public: - ~FramebufferImpl(); - Result init(DeviceImpl* device, const IFramebuffer::Desc& desc); }; diff --git a/tools/gfx/metal/metal-helper-functions.h b/tools/gfx/metal/metal-helper-functions.h index 0936cfa46..9fe4c9ff9 100644 --- a/tools/gfx/metal/metal-helper-functions.h +++ b/tools/gfx/metal/metal-helper-functions.h @@ -53,7 +53,6 @@ struct BindingOffset struct BindingContext { DeviceImpl* device = nullptr; - virtual void setData(const void* data, NS::UInteger length, NS::UInteger index) = 0; virtual void setBuffer(MTL::Buffer* buffer, NS::UInteger index) = 0; virtual void setTexture(MTL::Texture* texture, NS::UInteger index) = 0; virtual void setSampler(MTL::SamplerState* sampler, NS::UInteger index) = 0; @@ -70,11 +69,6 @@ struct ComputeBindingContext : public BindingContext return SLANG_OK; } - void setData(const void* data, NS::UInteger length, NS::UInteger index) override - { - encoder->setBytes(data, length, index); - } - void setBuffer(MTL::Buffer* buffer, NS::UInteger index) override { encoder->setBuffer(buffer, 0, index); @@ -91,6 +85,60 @@ struct ComputeBindingContext : public BindingContext } }; +struct VertexBindingContext : public BindingContext +{ + MTL::RenderCommandEncoder* encoder; + + Result init(DeviceImpl* device, MTL::RenderCommandEncoder* encoder) + { + this->device = device; + this->encoder = encoder; + return SLANG_OK; + } + + void setBuffer(MTL::Buffer* buffer, NS::UInteger index) override + { + encoder->setVertexBuffer(buffer, 0, index); + } + + void setTexture(MTL::Texture* texture, NS::UInteger index) override + { + encoder->setVertexTexture(texture, index); + } + + void setSampler(MTL::SamplerState* sampler, NS::UInteger index) override + { + encoder->setVertexSamplerState(sampler, index); + } +}; + +struct FragmentBindingContext : public BindingContext +{ + MTL::RenderCommandEncoder* encoder; + + Result init(DeviceImpl* device, MTL::RenderCommandEncoder* encoder) + { + this->device = device; + this->encoder = encoder; + return SLANG_OK; + } + + void setBuffer(MTL::Buffer* buffer, NS::UInteger index) override + { + encoder->setFragmentBuffer(buffer, 0, index); + } + + void setTexture(MTL::Texture* texture, NS::UInteger index) override + { + encoder->setFragmentTexture(texture, index); + } + + void setSampler(MTL::SamplerState* sampler, NS::UInteger index) override + { + encoder->setFragmentSamplerState(sampler, index); + } +}; + } // namespace metal Result SLANG_MCALL getMetalAdapters(List<AdapterInfo>& outAdapters); diff --git a/tools/gfx/metal/metal-pipeline-state.cpp b/tools/gfx/metal/metal-pipeline-state.cpp index b0fce682e..8daaeccda 100644 --- a/tools/gfx/metal/metal-pipeline-state.cpp +++ b/tools/gfx/metal/metal-pipeline-state.cpp @@ -50,40 +50,84 @@ void PipelineStateImpl::init(const RayTracingPipelineStateDesc& desc) Result PipelineStateImpl::createMetalRenderPipelineState() { - NS::SharedPtr<MTL::RenderPipelineDescriptor> pd = NS::TransferPtr(MTL::RenderPipelineDescriptor::alloc()->init()); auto programImpl = static_cast<ShaderProgramImpl*>(m_program.Ptr()); - if (programImpl) + if (!programImpl) + return SLANG_FAIL; + + NS::SharedPtr<MTL::RenderPipelineDescriptor> pd = NS::TransferPtr(MTL::RenderPipelineDescriptor::alloc()->init()); + + for (const ShaderProgramImpl::Module& module : programImpl->m_modules) { - SLANG_RETURN_ON_FAIL(programImpl->compileShaders(m_device)); + auto functionName = MetalUtil::createString(module.entryPointName.getBuffer()); + NS::SharedPtr<MTL::Function> function = NS::TransferPtr(module.library->newFunction(functionName.get())); + if (!function) + return SLANG_FAIL; + + switch (module.stage) + { + case SLANG_STAGE_VERTEX: + pd->setVertexFunction(function.get()); + break; + case SLANG_STAGE_FRAGMENT: + pd->setFragmentFunction(function.get()); + break; + default: + return SLANG_FAIL; + } } - const auto& programReflection = m_program->linkedProgram->getLayout(); - const auto& composedProgram = m_program->linkedProgram; - for (SlangUInt i = 0; i < programReflection->getEntryPointCount(); ++i) + // Offset vertex buffer indices in vertex layout. + // They need to be in a range not used by other buffer bindings. + m_vertexBufferOffset = 10; // TODO get from layout + auto inputLayoutImpl = static_cast<InputLayoutImpl*>(desc.graphics.inputLayout); + NS::SharedPtr<MTL::VertexDescriptor> vertexDescriptor = inputLayoutImpl->createVertexDescriptor(m_vertexBufferOffset); + pd->setVertexDescriptor(vertexDescriptor.get()); + pd->setInputPrimitiveTopology(MetalUtil::translatePrimitiveTopologyClass(desc.graphics.primitiveType)); + + // Set rasterization state + auto framebufferLayoutImpl = static_cast<FramebufferLayoutImpl*>(desc.graphics.framebufferLayout); + const auto& blend = desc.graphics.blend; + GfxCount sampleCount = 1; + + pd->setAlphaToCoverageEnabled(blend.alphaToCoverageEnable); + // pd->setAlphaToOneEnabled(); // Currently not supported by gfx + // pd->setRasterizationEnabled(true); // Enabled by default + + for (Index i = 0; i < framebufferLayoutImpl->m_renderTargets.getCount(); ++i) + { + const IFramebufferLayout::TargetLayout& targetLayout = framebufferLayoutImpl->m_renderTargets[i]; + MTL::RenderPipelineColorAttachmentDescriptor* colorAttachment = pd->colorAttachments()->object(i); + colorAttachment->setPixelFormat(MetalUtil::translatePixelFormat(targetLayout.format)); + if (i < blend.targetCount) + { + const TargetBlendDesc& targetBlendDesc = blend.targets[i]; + colorAttachment->setBlendingEnabled(targetBlendDesc.enableBlend); + colorAttachment->setSourceRGBBlendFactor(MetalUtil::translateBlendFactor(targetBlendDesc.color.srcFactor)); + colorAttachment->setDestinationRGBBlendFactor(MetalUtil::translateBlendFactor(targetBlendDesc.color.dstFactor)); + colorAttachment->setRgbBlendOperation(MetalUtil::translateBlendOperation(targetBlendDesc.color.op)); + colorAttachment->setSourceAlphaBlendFactor(MetalUtil::translateBlendFactor(targetBlendDesc.alpha.srcFactor)); + colorAttachment->setDestinationAlphaBlendFactor(MetalUtil::translateBlendFactor(targetBlendDesc.alpha.dstFactor)); + colorAttachment->setAlphaBlendOperation(MetalUtil::translateBlendOperation(targetBlendDesc.alpha.op)); + colorAttachment->setWriteMask(MetalUtil::translateColorWriteMask(targetBlendDesc.writeMask)); + } + sampleCount = Math::Max(sampleCount, targetLayout.sampleCount); + } + if (framebufferLayoutImpl->m_depthStencil.format != Format::Unknown) { - SlangStage stage = programReflection->getEntryPointByIndex(i)->getStage(); - if (stage == SLANG_STAGE_VERTEX) + const IFramebufferLayout::TargetLayout& depthStencil = framebufferLayoutImpl->m_depthStencil; + MTL::PixelFormat pixelFormat = MetalUtil::translatePixelFormat(depthStencil.format); + if (MetalUtil::isDepthFormat(pixelFormat)) + { + pd->setDepthAttachmentPixelFormat(MetalUtil::translatePixelFormat(depthStencil.format)); + } + if (MetalUtil::isStencilFormat(pixelFormat)) { - ComPtr<slang::IBlob> metalCode; - { - ComPtr<slang::IBlob> diagnosticsBlob; - SlangResult result = composedProgram->getEntryPointCode(i, 0, metalCode.writeRef(), diagnosticsBlob.writeRef()); - if (diagnosticsBlob) - { - std::cout << diagnosticsBlob->getBufferPointer() << std::endl; - } - //MTL::Function* f = ... - //RETURN_ON_FAIL(result); - //pd->setVertexFunction(); - } + pd->setStencilAttachmentPixelFormat(MetalUtil::translatePixelFormat(depthStencil.format)); } - //pd->setFragmentFunction(); } - // pd->colorAttachments()->object(0)->setPixelFormat(...); - // pd->setDepthAttachmentPixelFormat(...); - // Set deftault viewport and scissor - // Set default rasterization state - // Set default framebuffer layout + + pd->setRasterSampleCount(sampleCount); + NS::Error* error; m_renderPipelineState = NS::TransferPtr(m_device->m_device->newRenderPipelineState(pd.get(), &error)); if (!m_renderPipelineState) @@ -91,6 +135,38 @@ Result PipelineStateImpl::createMetalRenderPipelineState() std::cout << error->localizedDescription()->utf8String() << std::endl; return SLANG_E_INVALID_ARG; } + + // Create depth stencil state + auto createStencilDesc = [](const DepthStencilOpDesc& desc, uint32_t readMask, uint32_t writeMask) -> NS::SharedPtr<MTL::StencilDescriptor> + { + NS::SharedPtr<MTL::StencilDescriptor> stencilDesc = NS::TransferPtr(MTL::StencilDescriptor::alloc()->init()); + stencilDesc->setStencilCompareFunction(MetalUtil::translateCompareFunction(desc.stencilFunc)); + stencilDesc->setStencilFailureOperation(MetalUtil::translateStencilOperation(desc.stencilFailOp)); + stencilDesc->setDepthFailureOperation(MetalUtil::translateStencilOperation(desc.stencilDepthFailOp)); + stencilDesc->setDepthStencilPassOperation(MetalUtil::translateStencilOperation(desc.stencilPassOp)); + stencilDesc->setReadMask(readMask); + stencilDesc->setWriteMask(writeMask); + return stencilDesc; + }; + + const auto& depthStencil = desc.graphics.depthStencil; + NS::SharedPtr<MTL::DepthStencilDescriptor> depthStencilDesc = NS::TransferPtr(MTL::DepthStencilDescriptor::alloc()->init()); + m_depthStencilState = NS::TransferPtr(m_device->m_device->newDepthStencilState(depthStencilDesc.get())); + if (!m_depthStencilState) + { + return SLANG_FAIL; + } + if (depthStencil.depthTestEnable) + { + depthStencilDesc->setDepthCompareFunction(MetalUtil::translateCompareFunction(depthStencil.depthFunc)); + } + depthStencilDesc->setDepthWriteEnabled(depthStencil.depthWriteEnable); + if (depthStencil.stencilEnable) + { + depthStencilDesc->setFrontFaceStencil(createStencilDesc(depthStencil.frontFace, depthStencil.stencilReadMask, depthStencil.stencilWriteMask).get()); + depthStencilDesc->setBackFaceStencil(createStencilDesc(depthStencil.backFace, depthStencil.stencilReadMask, depthStencil.stencilWriteMask).get()); + } + return SLANG_OK; } @@ -100,10 +176,9 @@ Result PipelineStateImpl::createMetalComputePipelineState() if (!programImpl) return SLANG_FAIL; - NS::SharedPtr<MTL::ComputePipelineDescriptor> pd = NS::TransferPtr(MTL::ComputePipelineDescriptor::alloc()->init()); - - auto functionName = MetalUtil::createString(programImpl->m_entryPointNames[0].getBuffer()); - NS::SharedPtr<MTL::Function> function = NS::TransferPtr(programImpl->m_modules[0]->newFunction(functionName.get())); + const ShaderProgramImpl::Module& module = programImpl->m_modules[0]; + auto functionName = MetalUtil::createString(module.entryPointName.getBuffer()); + NS::SharedPtr<MTL::Function> function = NS::TransferPtr(module.library->newFunction(functionName.get())); if (!function) return SLANG_FAIL; @@ -120,6 +195,8 @@ Result PipelineStateImpl::createMetalComputePipelineState() Result PipelineStateImpl::ensureAPIPipelineStateCreated() { + AUTORELEASEPOOL + switch (desc.type) { case PipelineType::Compute: diff --git a/tools/gfx/metal/metal-pipeline-state.h b/tools/gfx/metal/metal-pipeline-state.h index e816af5b1..2a4f431b4 100644 --- a/tools/gfx/metal/metal-pipeline-state.h +++ b/tools/gfx/metal/metal-pipeline-state.h @@ -16,8 +16,10 @@ class PipelineStateImpl : public PipelineStateBase public: RefPtr<DeviceImpl> m_device; NS::SharedPtr<MTL::RenderPipelineState> m_renderPipelineState; + NS::SharedPtr<MTL::DepthStencilState> m_depthStencilState; NS::SharedPtr<MTL::ComputePipelineState> m_computePipelineState; MTL::Size m_threadGroupSize; + NS::UInteger m_vertexBufferOffset; PipelineStateImpl(DeviceImpl* device); ~PipelineStateImpl(); diff --git a/tools/gfx/metal/metal-render-pass.cpp b/tools/gfx/metal/metal-render-pass.cpp index f0849eb4b..bc60cf746 100644 --- a/tools/gfx/metal/metal-render-pass.cpp +++ b/tools/gfx/metal/metal-render-pass.cpp @@ -18,21 +18,18 @@ IRenderPassLayout* RenderPassLayoutImpl::getInterface(const Guid& guid) return nullptr; } -RenderPassLayoutImpl::~RenderPassLayoutImpl() -{ -} - static inline MTL::LoadAction translateLoadOp(IRenderPassLayout::TargetLoadOp loadOp) { switch (loadOp) { - case IRenderPassLayout::TargetLoadOp::Clear: - return MTL::LoadAction::LoadActionClear; case IRenderPassLayout::TargetLoadOp::Load: - return MTL::LoadAction::LoadActionLoad; + return MTL::LoadActionLoad; + case IRenderPassLayout::TargetLoadOp::Clear: + return MTL::LoadActionClear; case IRenderPassLayout::TargetLoadOp::DontCare: + return MTL::LoadActionDontCare; default: - return MTL::LoadAction::LoadActionDontCare; + return MTL::LoadAction(0); } } @@ -41,10 +38,11 @@ static inline MTL::StoreAction translateStoreOp(IRenderPassLayout::TargetStoreOp switch (storeOp) { case IRenderPassLayout::TargetStoreOp::Store: - return MTL::StoreAction::StoreActionStore; + return MTL::StoreActionStore; case IRenderPassLayout::TargetStoreOp::DontCare: + return MTL::StoreActionDontCare; default: - return MTL::StoreAction::StoreActionDontCare; + return MTL::StoreAction(0); } } @@ -57,27 +55,21 @@ Result RenderPassLayoutImpl::init(DeviceImpl* device, const IRenderPassLayout::D // Initialize render pass descriptor, filling in attachment metadata, but leaving texture data unbound. m_renderPassDesc = NS::TransferPtr(MTL::RenderPassDescriptor::alloc()->init()); - m_renderPassDesc->setRenderTargetArrayLength(desc.renderTargetCount); - MTL::RenderPassColorAttachmentDescriptorArray* colorAttachments = m_renderPassDesc->colorAttachments(); + m_renderPassDesc->setRenderTargetArrayLength(desc.renderTargetCount); for (GfxIndex i = 0; i < desc.renderTargetCount; ++i) { - MTL::RenderPassColorAttachmentDescriptor* colorAttach = MTL::RenderPassColorAttachmentDescriptor::alloc()->init(); - colorAttach->setLoadAction(translateLoadOp(desc.renderTargetAccess[i].loadOp)); - colorAttach->setStoreAction(translateStoreOp(desc.renderTargetAccess[i].storeOp)); - // We set the texture when the render pass is executed, using the associated framebuffer. - colorAttach->setTexture(nullptr); - colorAttachments->setObject(colorAttach, i); + MTL::RenderPassColorAttachmentDescriptor* colorAttachment = m_renderPassDesc->colorAttachments()->object(i); + colorAttachment->setLoadAction(translateLoadOp(desc.renderTargetAccess[i].loadOp)); + colorAttachment->setStoreAction(translateStoreOp(desc.renderTargetAccess[i].storeOp)); } + m_renderPassDesc->depthAttachment()->setLoadAction(translateLoadOp(desc.depthStencilAccess->loadOp)); m_renderPassDesc->depthAttachment()->setStoreAction(translateStoreOp(desc.depthStencilAccess->storeOp)); - // We set the depth texture when the render pass is executed, using the associated framebuffer. - m_renderPassDesc->depthAttachment()->setTexture(nullptr); - //m_renderPassDesc->depthAttachment()->setClearDepth(1000000.); + m_renderPassDesc->stencilAttachment()->setLoadAction(translateLoadOp(desc.depthStencilAccess->loadOp)); m_renderPassDesc->stencilAttachment()->setStoreAction(translateStoreOp(desc.depthStencilAccess->storeOp)); - // We set the stencil texture when the render pass is executed, using the associated framebuffer. - m_renderPassDesc->stencilAttachment()->setTexture(nullptr); + return SLANG_OK; } diff --git a/tools/gfx/metal/metal-render-pass.h b/tools/gfx/metal/metal-render-pass.h index ef69d8909..ee66b0c4d 100644 --- a/tools/gfx/metal/metal-render-pass.h +++ b/tools/gfx/metal/metal-render-pass.h @@ -24,8 +24,6 @@ public: RefPtr<DeviceImpl> m_device; NS::SharedPtr<MTL::RenderPassDescriptor> m_renderPassDesc; - ~RenderPassLayoutImpl(); - Result init(DeviceImpl* device, const IRenderPassLayout::Desc& desc); }; diff --git a/tools/gfx/metal/metal-shader-program.cpp b/tools/gfx/metal/metal-shader-program.cpp index 1b998bc57..e0f973eb6 100644 --- a/tools/gfx/metal/metal-shader-program.cpp +++ b/tools/gfx/metal/metal-shader-program.cpp @@ -22,19 +22,22 @@ ShaderProgramImpl::~ShaderProgramImpl() Result ShaderProgramImpl::createShaderModule(slang::EntryPointReflection* entryPointInfo, ComPtr<ISlangBlob> kernelCode) { - m_codeBlobs.add(kernelCode); - const char* realEntryPointName = entryPointInfo->getNameOverride(); + Module module; + module.stage = entryPointInfo->getStage(); + module.entryPointName = entryPointInfo->getNameOverride(); + module.code = kernelCode; + dispatch_data_t data = dispatch_data_create(kernelCode->getBufferPointer(), kernelCode->getBufferSize(), dispatch_get_main_queue(), NULL); NS::Error* error; - NS::SharedPtr<MTL::Library> library = NS::TransferPtr(m_device->m_device->newLibrary(data, &error)); - if (!library) + module.library = NS::TransferPtr(m_device->m_device->newLibrary(data, &error)); + if (!module.library) { // TODO use better mechanism for reporting errors std::cout << error->localizedDescription()->utf8String() << std::endl; return SLANG_E_INVALID_ARG; } - m_entryPointNames.add(realEntryPointName); - m_modules.add(library); + + m_modules.add(module); return SLANG_OK; } diff --git a/tools/gfx/metal/metal-shader-program.h b/tools/gfx/metal/metal-shader-program.h index 50f568321..ed2f231ec 100644 --- a/tools/gfx/metal/metal-shader-program.h +++ b/tools/gfx/metal/metal-shader-program.h @@ -16,12 +16,18 @@ class ShaderProgramImpl : public ShaderProgramBase { public: BreakableReference<DeviceImpl> m_device; - - List<String> m_entryPointNames; - List<ComPtr<ISlangBlob>> m_codeBlobs; //< To keep storage of code in scope - List<NS::SharedPtr<MTL::Library>> m_modules; RefPtr<RootShaderObjectLayoutImpl> m_rootObjectLayout; + struct Module + { + SlangStage stage; + String entryPointName; + ComPtr<ISlangBlob> code; + NS::SharedPtr<MTL::Library> library; + }; + + List<Module> m_modules; + ShaderProgramImpl(DeviceImpl* device); ~ShaderProgramImpl(); diff --git a/tools/gfx/metal/metal-swap-chain.cpp b/tools/gfx/metal/metal-swap-chain.cpp index 0a28b214c..1478c8bf4 100644 --- a/tools/gfx/metal/metal-swap-chain.cpp +++ b/tools/gfx/metal/metal-swap-chain.cpp @@ -24,6 +24,26 @@ void SwapchainImpl::getWindowSize(int& widthOut, int& heightOut) const CocoaUtil::getNSWindowContentSize((void*)m_windowHandle.handleValues[0], &widthOut, &heightOut); } +void SwapchainImpl::createImages() +{ + m_images.setCount(m_desc.imageCount); + for (GfxCount i = 0; i < m_desc.imageCount; ++i) + { + ITextureResource::Desc imageDesc = {}; + imageDesc.allowedStates = ResourceStateSet( + ResourceState::Present, ResourceState::RenderTarget, ResourceState::CopyDestination, ResourceState::CopySource); + imageDesc.type = IResource::Type::Texture2D; + imageDesc.arraySize = 0; + imageDesc.format = m_desc.format; + imageDesc.size.width = m_desc.width; + imageDesc.size.height = m_desc.height; + imageDesc.size.depth = 1; + imageDesc.numMipLevels = 1; + imageDesc.defaultState = ResourceState::Present; + m_device->createTextureResource(imageDesc, nullptr, (gfx::ITextureResource**)m_images[i].writeRef()); + } +} + SwapchainImpl::~SwapchainImpl() { m_images.clear(); @@ -36,7 +56,7 @@ Result SwapchainImpl::init(DeviceImpl* device, const ISwapchain::Desc& desc, Win m_desc = desc; m_windowHandle = window; m_metalFormat = MetalUtil::translatePixelFormat(desc.format); - m_currentImageIndex = 0; + m_currentImageIndex = -1; getWindowSize(m_desc.width, m_desc.height); @@ -48,14 +68,17 @@ Result SwapchainImpl::init(DeviceImpl* device, const ISwapchain::Desc& desc, Win m_metalLayer->setPixelFormat(m_metalFormat); m_metalLayer->setDevice(m_device->m_device.get()); m_metalLayer->setDrawableSize(CGSize{(float)m_desc.width, (float)m_desc.height}); - m_metalLayer->setFramebufferOnly(true); + // We need to be able to copy from a texture. + m_metalLayer->setFramebufferOnly(false); + + createImages(); return SLANG_OK; } Result SwapchainImpl::getImage(GfxIndex index, ITextureResource** outResource) { - if (index < 0 || index != m_currentImageIndex) + if (index < 0 || index >= m_desc.imageCount) return SLANG_FAIL; returnComPtr(outResource, m_images[index]); return SLANG_OK; @@ -63,24 +86,27 @@ Result SwapchainImpl::getImage(GfxIndex index, ITextureResource** outResource) Result SwapchainImpl::resize(GfxCount width, GfxCount height) { - SLANG_UNUSED(width); - SLANG_UNUSED(height); - m_images.clear(); m_currentImageIndex = -1; m_currentDrawable.reset(); getWindowSize(m_desc.width, m_desc.height); m_metalLayer->setDrawableSize(CGSize{(float)m_desc.width, (float)m_desc.height}); + createImages(); return SLANG_OK; } Result SwapchainImpl::present() { + AUTORELEASEPOOL + if (!m_currentDrawable) { return SLANG_FAIL; } MTL::CommandBuffer* commandBuffer = m_device->m_commandQueue->commandBuffer(); + MTL::BlitCommandEncoder* encoder = commandBuffer->blitCommandEncoder(); + encoder->copyFromTexture(m_images[m_currentImageIndex]->m_texture.get(), m_currentDrawable->texture()); + encoder->endEncoding(); commandBuffer->presentDrawable(m_currentDrawable.get()); commandBuffer->commit(); m_currentDrawable.reset(); @@ -103,48 +129,22 @@ int SwapchainImpl::acquireNextImage() { AUTORELEASEPOOL - CA::MetalDrawable* drawable = m_metalLayer->nextDrawable(); - if (drawable == nullptr) + m_currentDrawable = NS::RetainPtr(m_metalLayer->nextDrawable()); + if (m_currentDrawable) { - return -1; + m_currentImageIndex = (m_currentImageIndex + 1) % m_desc.imageCount; } - - m_currentDrawable = NS::RetainPtr(drawable); - MTL::Texture* texture = drawable->texture(); - - // Check if we got a texture we've seen before. - for (Index i = 0; i < m_images.getCount(); i++) + else { - if (m_images[i]->m_texture.get() == texture) - { - m_currentImageIndex = i; - return m_currentImageIndex; - } + m_currentImageIndex = -1; } - - // Create a new texture object to wrap the drawable's texture. - - ITextureResource::Desc desc = {}; - desc.allowedStates = ResourceStateSet( - ResourceState::Present, ResourceState::RenderTarget, ResourceState::CopyDestination); - desc.type = IResource::Type::Texture2D; - desc.arraySize = 0; - desc.format = m_desc.format; // TODO use actual pixelformat - desc.size.width = texture->width(); - desc.size.height = texture->height(); - desc.size.depth = 1; - desc.numMipLevels = 1; - desc.defaultState = ResourceState::Present; - RefPtr<TextureResourceImpl> image = new TextureResourceImpl(desc, m_device); - image->m_texture = NS::RetainPtr(texture); - - m_currentImageIndex = m_images.getCount(); - m_images.add(image); - return m_currentImageIndex; } -Result SwapchainImpl::setFullScreenMode(bool mode) { return SLANG_FAIL; } +Result SwapchainImpl::setFullScreenMode(bool mode) +{ + return SLANG_E_NOT_AVAILABLE; +} } // namespace metal } // namespace gfx diff --git a/tools/gfx/metal/metal-swap-chain.h b/tools/gfx/metal/metal-swap-chain.h index bed1c0f5b..b7d57e271 100644 --- a/tools/gfx/metal/metal-swap-chain.h +++ b/tools/gfx/metal/metal-swap-chain.h @@ -28,11 +28,12 @@ public: WindowHandle m_windowHandle; CA::MetalLayer* m_metalLayer = nullptr; ShortList<RefPtr<TextureResourceImpl>> m_images; - NS::SharedPtr<MTL::Drawable> m_currentDrawable; + NS::SharedPtr<CA::MetalDrawable> m_currentDrawable; Index m_currentImageIndex = -1; MTL::PixelFormat m_metalFormat = MTL::PixelFormat::PixelFormatInvalid; void getWindowSize(int& widthOut, int& heightOut) const; + void createImages(); public: ~SwapchainImpl(); diff --git a/tools/gfx/metal/metal-texture.h b/tools/gfx/metal/metal-texture.h index 853af7ab0..8f8ab3576 100644 --- a/tools/gfx/metal/metal-texture.h +++ b/tools/gfx/metal/metal-texture.h @@ -20,7 +20,7 @@ public: TextureResourceImpl(const Desc& desc, DeviceImpl* device); ~TextureResourceImpl(); - RefPtr<DeviceImpl> m_device; + BreakableReference<DeviceImpl> m_device; NS::SharedPtr<MTL::Texture> m_texture; // TODO still needed? // MTL::PixelFormat m_metalFormat = MTL::PixelFormat::PixelFormatInvalid; diff --git a/tools/gfx/metal/metal-util.cpp b/tools/gfx/metal/metal-util.cpp index d7d2a793d..ed96eb487 100644 --- a/tools/gfx/metal/metal-util.cpp +++ b/tools/gfx/metal/metal-util.cpp @@ -176,6 +176,35 @@ MTL::VertexFormat MetalUtil::translateVertexFormat(Format format) } } +bool MetalUtil::isDepthFormat(MTL::PixelFormat format) +{ + switch (format) + { + case MTL::PixelFormatDepth16Unorm: + case MTL::PixelFormatDepth32Float: + case MTL::PixelFormatDepth24Unorm_Stencil8: + case MTL::PixelFormatDepth32Float_Stencil8: + return true; + default: + return false; + } +} + +bool MetalUtil::isStencilFormat(MTL::PixelFormat format) +{ + switch (format) + { + case MTL::PixelFormatStencil8: + case MTL::PixelFormatDepth24Unorm_Stencil8: + case MTL::PixelFormatDepth32Float_Stencil8: + case MTL::PixelFormatX32_Stencil8: + case MTL::PixelFormatX24_Stencil8: + return true; + default: + return false; + } +} + MTL::SamplerMinMagFilter MetalUtil::translateSamplerMinMagFilter(TextureFilteringMode mode) { switch (mode) @@ -246,6 +275,31 @@ MTL::CompareFunction MetalUtil::translateCompareFunction(ComparisonFunc func) } } +MTL::StencilOperation MetalUtil::translateStencilOperation(StencilOp op) +{ + switch (op) + { + case StencilOp::Keep: + return MTL::StencilOperationKeep; + case StencilOp::Zero: + return MTL::StencilOperationZero; + case StencilOp::Replace: + return MTL::StencilOperationReplace; + case StencilOp::IncrementSaturate: + return MTL::StencilOperationIncrementClamp; + case StencilOp::DecrementSaturate: + return MTL::StencilOperationDecrementClamp; + case StencilOp::Invert: + return MTL::StencilOperationInvert; + case StencilOp::IncrementWrap: + return MTL::StencilOperationIncrementWrap; + case StencilOp::DecrementWrap: + return MTL::StencilOperationDecrementWrap; + default: + return MTL::StencilOperation(0); + } +} + MTL::VertexStepFunction MetalUtil::translateVertexStepFunction(InputSlotClass slotClass) { switch (slotClass) @@ -259,4 +313,156 @@ MTL::VertexStepFunction MetalUtil::translateVertexStepFunction(InputSlotClass sl } } +MTL::PrimitiveType MetalUtil::translatePrimitiveType(PrimitiveTopology topology) +{ + switch (topology) + { + case PrimitiveTopology::TriangleList: + return MTL::PrimitiveTypeTriangle; + case PrimitiveTopology::TriangleStrip: + return MTL::PrimitiveTypeTriangleStrip; + case PrimitiveTopology::PointList: + return MTL::PrimitiveTypePoint; + case PrimitiveTopology::LineList: + return MTL::PrimitiveTypeLine; + case PrimitiveTopology::LineStrip: + return MTL::PrimitiveTypeLineStrip; + default: + return MTL::PrimitiveType(0); + } +} + +MTL::PrimitiveTopologyClass MetalUtil::translatePrimitiveTopologyClass(PrimitiveType type) +{ + switch (type) + { + case PrimitiveType::Point: + return MTL::PrimitiveTopologyClassPoint; + case PrimitiveType::Line: + return MTL::PrimitiveTopologyClassLine; + case PrimitiveType::Triangle: + return MTL::PrimitiveTopologyClassTriangle; + case PrimitiveType::Patch: + default: + return MTL::PrimitiveTopologyClassUnspecified; + } +} + +MTL::BlendFactor MetalUtil::translateBlendFactor(BlendFactor factor) +{ + switch (factor) + { + case BlendFactor::Zero: + return MTL::BlendFactorZero; + case BlendFactor::One: + return MTL::BlendFactorOne; + case BlendFactor::SrcColor: + return MTL::BlendFactorSourceColor; + case BlendFactor::InvSrcColor: + return MTL::BlendFactorOneMinusSourceColor; + case BlendFactor::SrcAlpha: + return MTL::BlendFactorSourceAlpha; + case BlendFactor::InvSrcAlpha: + return MTL::BlendFactorOneMinusSourceAlpha; + case BlendFactor::DestAlpha: + return MTL::BlendFactorDestinationAlpha; + case BlendFactor::InvDestAlpha: + return MTL::BlendFactorOneMinusDestinationAlpha; + case BlendFactor::DestColor: + return MTL::BlendFactorDestinationColor; + case BlendFactor::InvDestColor: + return MTL::BlendFactorOneMinusDestinationColor; + case BlendFactor::SrcAlphaSaturate: + return MTL::BlendFactorSourceAlphaSaturated; + case BlendFactor::BlendColor: + return MTL::BlendFactorBlendColor; + case BlendFactor::InvBlendColor: + return MTL::BlendFactorOneMinusBlendColor; + case BlendFactor::SecondarySrcColor: + return MTL::BlendFactorSource1Color; + case BlendFactor::InvSecondarySrcColor: + return MTL::BlendFactorOneMinusSource1Color; + case BlendFactor::SecondarySrcAlpha: + return MTL::BlendFactorSource1Alpha; + case BlendFactor::InvSecondarySrcAlpha: + return MTL::BlendFactorOneMinusSource1Alpha; + default: + return MTL::BlendFactor(0); + } +} + +MTL::BlendOperation MetalUtil::translateBlendOperation(BlendOp op) +{ + switch (op) + { + case BlendOp::Add: + return MTL::BlendOperationAdd; + case BlendOp::Subtract: + return MTL::BlendOperationSubtract; + case BlendOp::ReverseSubtract: + return MTL::BlendOperationReverseSubtract; + case BlendOp::Min: + return MTL::BlendOperationMin; + case BlendOp::Max: + return MTL::BlendOperationMax; + default: + return MTL::BlendOperation(0); + } +} + +MTL::ColorWriteMask MetalUtil::translateColorWriteMask(RenderTargetWriteMask::Type mask) +{ + MTL::ColorWriteMask result = MTL::ColorWriteMaskNone; + if (mask & RenderTargetWriteMask::EnableRed) + result |= MTL::ColorWriteMaskRed; + if (mask & RenderTargetWriteMask::EnableGreen) + result |= MTL::ColorWriteMaskGreen; + if (mask & RenderTargetWriteMask::EnableBlue) + result |= MTL::ColorWriteMaskBlue; + if (mask & RenderTargetWriteMask::EnableAlpha) + result |= MTL::ColorWriteMaskAlpha; + return result; +} + +MTL::Winding MetalUtil::translateWinding(FrontFaceMode mode) +{ + switch (mode) + { + case FrontFaceMode::CounterClockwise: + return MTL::WindingCounterClockwise; + case FrontFaceMode::Clockwise: + return MTL::WindingClockwise; + default: + return MTL::Winding(0); + } +} + +MTL::CullMode MetalUtil::translateCullMode(CullMode mode) +{ + switch (mode) + { + case CullMode::None: + return MTL::CullModeNone; + case CullMode::Front: + return MTL::CullModeFront; + case CullMode::Back: + return MTL::CullModeBack; + default: + return MTL::CullMode(0); + } +} + +MTL::TriangleFillMode MetalUtil::translateTriangleFillMode(FillMode mode) +{ + switch (mode) + { + case FillMode::Solid: + return MTL::TriangleFillModeFill; + case FillMode::Wireframe: + return MTL::TriangleFillModeLines; + default: + return MTL::TriangleFillMode(0); + } +} + } // namespace gfx diff --git a/tools/gfx/metal/metal-util.h b/tools/gfx/metal/metal-util.h index 617d82e29..279f0c67e 100644 --- a/tools/gfx/metal/metal-util.h +++ b/tools/gfx/metal/metal-util.h @@ -25,31 +25,28 @@ struct MetalUtil static MTL::PixelFormat translatePixelFormat(Format format); static MTL::VertexFormat translateVertexFormat(Format format); - static inline bool isDepthFormat(MTL::PixelFormat format) - { - switch (format) - { - return true; - } - return false; - } - - static inline bool isStencilFormat(MTL::PixelFormat format) - { - switch (format) - { - return true; - } - return false; - } + static bool isDepthFormat(MTL::PixelFormat format); + static bool isStencilFormat(MTL::PixelFormat format); static MTL::SamplerMinMagFilter translateSamplerMinMagFilter(TextureFilteringMode mode); static MTL::SamplerMipFilter translateSamplerMipFilter(TextureFilteringMode mode); static MTL::SamplerAddressMode translateSamplerAddressMode(TextureAddressingMode mode); static MTL::CompareFunction translateCompareFunction(ComparisonFunc func); + static MTL::StencilOperation translateStencilOperation(StencilOp op); static MTL::VertexStepFunction translateVertexStepFunction(InputSlotClass slotClass); + static MTL::PrimitiveType translatePrimitiveType(PrimitiveTopology topology); + static MTL::PrimitiveTopologyClass translatePrimitiveTopologyClass(PrimitiveType type); + + static MTL::BlendFactor translateBlendFactor(BlendFactor factor); + static MTL::BlendOperation translateBlendOperation(BlendOp op); + static MTL::ColorWriteMask translateColorWriteMask(RenderTargetWriteMask::Type mask); + + static MTL::Winding translateWinding(FrontFaceMode mode); + static MTL::CullMode translateCullMode(CullMode mode); + static MTL::TriangleFillMode translateTriangleFillMode(FillMode mode); + }; struct ScopedAutoreleasePool diff --git a/tools/gfx/metal/metal-vertex-layout.cpp b/tools/gfx/metal/metal-vertex-layout.cpp new file mode 100644 index 000000000..686f3ad0c --- /dev/null +++ b/tools/gfx/metal/metal-vertex-layout.cpp @@ -0,0 +1,57 @@ +// metal-vertex-layout.cpp +#include "metal-vertex-layout.h" +#include "metal-util.h" + +namespace gfx +{ + +using namespace Slang; + +namespace metal +{ + +Result InputLayoutImpl::init(const IInputLayout::Desc& desc) +{ + for (Index i = 0; i < desc.inputElementCount; i++) + { + if (MetalUtil::translateVertexFormat(desc.inputElements[i].format) == MTL::VertexFormatInvalid) + { + return SLANG_E_INVALID_ARG; + } + m_inputElements.add(desc.inputElements[i]); + } + for (Index i = 0; i < desc.vertexStreamCount; i++) + { + m_vertexStreams.add(desc.vertexStreams[i]); + } + return SLANG_OK; +} + +NS::SharedPtr<MTL::VertexDescriptor> InputLayoutImpl::createVertexDescriptor(NS::UInteger vertexBufferIndexOffset) +{ + NS::SharedPtr<MTL::VertexDescriptor> vertexDescriptor = NS::TransferPtr(MTL::VertexDescriptor::alloc()->init()); + + for (Index i = 0; i < m_inputElements.getCount(); i++) + { + const auto& inputElement = m_inputElements[i]; + MTL::VertexAttributeDescriptor* desc = vertexDescriptor->attributes()->object(i); + desc->setOffset(inputElement.offset); + desc->setBufferIndex(inputElement.bufferSlotIndex + vertexBufferIndexOffset); + MTL::VertexFormat metalFormat = MetalUtil::translateVertexFormat(inputElement.format); + desc->setFormat(metalFormat); + } + + for (Index i = 0; i < m_vertexStreams.getCount(); i++) + { + const auto& vertexStream = m_vertexStreams[i]; + MTL::VertexBufferLayoutDescriptor* desc = vertexDescriptor->layouts()->object(i + vertexBufferIndexOffset); + desc->setStepFunction(MetalUtil::translateVertexStepFunction(vertexStream.slotClass)); + desc->setStepRate(vertexStream.slotClass == InputSlotClass::PerVertex ? 1 : vertexStream.instanceDataStepRate); + desc->setStride(vertexStream.stride); + } + + return vertexDescriptor; +} + +} // namespace metal +} // namespace gfx diff --git a/tools/gfx/metal/metal-vertex-layout.h b/tools/gfx/metal/metal-vertex-layout.h index b0f989efd..5cfdf3dc6 100644 --- a/tools/gfx/metal/metal-vertex-layout.h +++ b/tools/gfx/metal/metal-vertex-layout.h @@ -14,7 +14,11 @@ namespace metal class InputLayoutImpl : public InputLayoutBase { public: - NS::SharedPtr<MTL::VertexDescriptor> m_vertexDescriptor; + List<InputElementDesc> m_inputElements; + List<VertexStreamDesc> m_vertexStreams; + + Result init(const IInputLayout::Desc& desc); + NS::SharedPtr<MTL::VertexDescriptor> createVertexDescriptor(NS::UInteger vertexBufferIndexOffset); }; } // namespace metal diff --git a/tools/gfx/vulkan/vk-fence.cpp b/tools/gfx/vulkan/vk-fence.cpp index f81f56ca7..d71847dcb 100644 --- a/tools/gfx/vulkan/vk-fence.cpp +++ b/tools/gfx/vulkan/vk-fence.cpp @@ -52,7 +52,7 @@ Result FenceImpl::init(const IFence::Desc& desc) { #if SLANG_WINDOWS_FAMILY exportSemaphoreWin32HandleInfoKHR.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR; - exportSemaphoreWin32HandleInfoKHR.pNext = timelineCreateInfo.pNext;; + exportSemaphoreWin32HandleInfoKHR.pNext = timelineCreateInfo.pNext; exportSemaphoreWin32HandleInfoKHR.pAttributes = nullptr; exportSemaphoreWin32HandleInfoKHR.dwAccess = GENERIC_ALL; exportSemaphoreWin32HandleInfoKHR.name = (LPCWSTR)nullptr; |
