diff options
| author | skallweitNV <64953474+skallweitNV@users.noreply.github.com> | 2024-06-11 17:21:45 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-11 08:21:45 -0700 |
| commit | 5a289681e511ec419829291c7281cdd3c7918b7f (patch) | |
| tree | a1dd2c5d6fb3eaff5f17f9c0033326c1fd52dbd5 /tools | |
| parent | df0a201d85eac4c55c1abf15ed0bf9baea0ae971 (diff) | |
[gfx] Metal texture fixes (#4331)
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gfx/metal/metal-command-buffer.cpp | 4 | ||||
| -rw-r--r-- | tools/gfx/metal/metal-command-encoder.cpp | 6 | ||||
| -rw-r--r-- | tools/gfx/metal/metal-device.cpp | 125 | ||||
| -rw-r--r-- | tools/gfx/metal/metal-pipeline-state.cpp | 13 | ||||
| -rw-r--r-- | tools/gfx/metal/metal-resource-views.h | 1 | ||||
| -rw-r--r-- | tools/gfx/metal/metal-shader-object.cpp | 2 | ||||
| -rw-r--r-- | tools/gfx/metal/metal-texture.h | 5 |
7 files changed, 103 insertions, 53 deletions
diff --git a/tools/gfx/metal/metal-command-buffer.cpp b/tools/gfx/metal/metal-command-buffer.cpp index c54552ae4..3f9923bf8 100644 --- a/tools/gfx/metal/metal-command-buffer.cpp +++ b/tools/gfx/metal/metal-command-buffer.cpp @@ -77,7 +77,9 @@ void CommandBufferImpl::close() Result CommandBufferImpl::getNativeHandle(InteropHandle* outHandle) { - return SLANG_E_NOT_IMPLEMENTED; + outHandle->api = InteropHandleAPI::Metal; + outHandle->handleValue = reinterpret_cast<intptr_t>(m_commandBuffer.get()); + return SLANG_OK; } MTL::RenderCommandEncoder* CommandBufferImpl::getMetalRenderCommandEncoder(MTL::RenderPassDescriptor* renderPassDesc) diff --git a/tools/gfx/metal/metal-command-encoder.cpp b/tools/gfx/metal/metal-command-encoder.cpp index 3e0fbd1f6..fa1df263e 100644 --- a/tools/gfx/metal/metal-command-encoder.cpp +++ b/tools/gfx/metal/metal-command-encoder.cpp @@ -227,7 +227,7 @@ void RenderCommandEncoder::beginPass(IRenderPassLayout* renderPass, IFramebuffer { TextureResourceViewImpl* renderTargetView = m_framebuffer->m_renderTargetViews[i]; MTL::RenderPassColorAttachmentDescriptor* colorAttachment = m_renderPassDesc->colorAttachments()->object(i); - colorAttachment->setTexture(renderTargetView->m_texture->m_texture.get()); + colorAttachment->setTexture(renderTargetView->m_textureView.get()); colorAttachment->setLevel(renderTargetView->m_desc.subresourceRange.mipLevel); colorAttachment->setSlice(renderTargetView->m_desc.subresourceRange.baseArrayLayer); } @@ -239,14 +239,14 @@ void RenderCommandEncoder::beginPass(IRenderPassLayout* renderPass, IFramebuffer if (MetalUtil::isDepthFormat(pixelFormat)) { MTL::RenderPassDepthAttachmentDescriptor* depthAttachment = m_renderPassDesc->depthAttachment(); - depthAttachment->setTexture(depthStencilView->m_texture->m_texture.get()); + depthAttachment->setTexture(depthStencilView->m_textureView.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->setTexture(depthStencilView->m_textureView.get()); stencilAttachment->setLevel(depthStencilView->m_desc.subresourceRange.mipLevel); stencilAttachment->setSlice(depthStencilView->m_desc.subresourceRange.baseArrayLayer); } diff --git a/tools/gfx/metal/metal-device.cpp b/tools/gfx/metal/metal-device.cpp index a4cf23da3..1be9d1019 100644 --- a/tools/gfx/metal/metal-device.cpp +++ b/tools/gfx/metal/metal-device.cpp @@ -292,6 +292,11 @@ Result DeviceImpl::createTextureResource( TextureResource::Desc desc = fixupTextureDesc(descIn); + // Metal doesn't support mip-mapping for 1D textures + // However, we still need to use the provided mip level count when initializing the texture + Count initMipLevels = desc.numMipLevels; + desc.numMipLevels = desc.type == IResource::Type::Texture1D ? 1 : desc.numMipLevels; + const MTL::PixelFormat pixelFormat = MetalUtil::translatePixelFormat(desc.format); if (pixelFormat == MTL::PixelFormat::PixelFormatInvalid) { @@ -316,29 +321,29 @@ Result DeviceImpl::createTextureResource( break; } - NS::UInteger arrayLength = calcEffectiveArraySize(desc); + bool isArray = desc.arraySize > 0; switch (desc.type) { case IResource::Type::Texture1D: - textureDesc->setTextureType(arrayLength > 1 ? MTL::TextureType1DArray : MTL::TextureType1D); + textureDesc->setTextureType(isArray ? MTL::TextureType1DArray : MTL::TextureType1D); textureDesc->setWidth(desc.size.width); break; case IResource::Type::Texture2D: if (desc.sampleDesc.numSamples > 1) { - textureDesc->setTextureType(arrayLength > 1 ? MTL::TextureType2DMultisampleArray : MTL::TextureType2DMultisample); + textureDesc->setTextureType(isArray ? MTL::TextureType2DMultisampleArray : MTL::TextureType2DMultisample); textureDesc->setSampleCount(desc.sampleDesc.numSamples); } else { - textureDesc->setTextureType(arrayLength > 1 ? MTL::TextureType2DArray : MTL::TextureType2D); + textureDesc->setTextureType(isArray ? MTL::TextureType2DArray : MTL::TextureType2D); } textureDesc->setWidth(descIn.size.width); textureDesc->setHeight(descIn.size.height); break; case IResource::Type::TextureCube: - textureDesc->setTextureType(arrayLength > 6 ? MTL::TextureTypeCubeArray : MTL::TextureTypeCube); + textureDesc->setTextureType(isArray ? MTL::TextureTypeCubeArray : MTL::TextureTypeCube); textureDesc->setWidth(descIn.size.width); textureDesc->setHeight(descIn.size.height); break; @@ -369,7 +374,7 @@ Result DeviceImpl::createTextureResource( } textureDesc->setMipmapLevelCount(desc.numMipLevels); - textureDesc->setArrayLength(arrayLength); + textureDesc->setArrayLength(isArray ? desc.arraySize : 1); textureDesc->setPixelFormat(pixelFormat); textureDesc->setUsage(textureUsage); textureDesc->setSampleCount(desc.sampleDesc.numSamples); @@ -380,8 +385,52 @@ Result DeviceImpl::createTextureResource( { return SLANG_FAIL; } + textureImpl->m_textureType = textureDesc->textureType(); + textureImpl->m_pixelFormat = textureDesc->pixelFormat(); // TODO: handle initData + if (initData) + { + textureDesc->setStorageMode(MTL::StorageModeManaged); + textureDesc->setCpuCacheMode(MTL::CPUCacheModeDefaultCache); + NS::SharedPtr<MTL::Texture> stagingTexture = NS::TransferPtr(m_device->newTexture(textureDesc.get())); + + MTL::CommandBuffer* commandBuffer = m_commandQueue->commandBuffer(); + MTL::BlitCommandEncoder* encoder = commandBuffer->blitCommandEncoder(); + if (!stagingTexture || !commandBuffer || !encoder) + { + return SLANG_FAIL; + } + + Count sliceCount = isArray ? desc.arraySize : 1; + if (desc.type == IResource::Type::TextureCube) + { + sliceCount *= 6; + } + + for (Index slice = 0; slice < sliceCount; ++slice) + { + MTL::Region region; + region.origin = MTL::Origin(0, 0, 0); + region.size = MTL::Size(desc.size.width, desc.size.height, desc.size.depth); + for (Index level = 0; level < initMipLevels; ++level) + { + if (level >= desc.numMipLevels) + continue; + const ITextureResource::SubresourceData& subresourceData = initData[slice * initMipLevels + level]; + stagingTexture->replaceRegion(region, level, slice, subresourceData.data, subresourceData.strideY, subresourceData.strideZ); + encoder->synchronizeTexture(stagingTexture.get(), slice, level); + region.size.width = region.size.width > 0 ? Math::Max(1ul, region.size.width >> 1) : 0; + region.size.height = region.size.height > 0 ? Math::Max(1ul, region.size.height >> 1) : 0; + region.size.depth = region.size.depth > 0 ? Math::Max(1ul, region.size.depth >> 1) : 0; + } + } + + encoder->copyFromTexture(stagingTexture.get(), textureImpl->m_texture.get()); + encoder->endEncoding(); + commandBuffer->commit(); + commandBuffer->waitUntilCompleted(); + } returnComPtr(outResource, textureImpl); return SLANG_OK; @@ -461,52 +510,40 @@ Result DeviceImpl::createTextureView( { AUTORELEASEPOOL - auto resourceImpl = static_cast<TextureResourceImpl*>(texture); - RefPtr<TextureResourceViewImpl> view = new TextureResourceViewImpl(this); - view->m_desc = desc; - view->m_device = this; - if (texture == nullptr) + auto textureImpl = static_cast<TextureResourceImpl*>(texture); + RefPtr<TextureResourceViewImpl> viewImpl = new TextureResourceViewImpl(this); + viewImpl->m_desc = desc; + viewImpl->m_device = this; + viewImpl->m_texture = textureImpl; + if (textureImpl == nullptr) { - view->m_texture = nullptr; - returnComPtr(outView, view); + returnComPtr(outView, viewImpl); return SLANG_OK; } - bool isArray = resourceImpl->getDesc()->arraySize > 1; - MTL::PixelFormat pixelFormat = MetalUtil::translatePixelFormat(desc.format); - NS::Range levelRange(desc.subresourceRange.baseArrayLayer, std::max(desc.subresourceRange.layerCount, 1)); - NS::Range sliceRange(desc.subresourceRange.mipLevel, std::max(desc.subresourceRange.mipLevelCount, 1)); - MTL::TextureType textureType; - switch (resourceImpl->getType()) - { - case IResource::Type::Texture1D: - textureType = isArray ? MTL::TextureType1DArray : MTL::TextureType1D; - break; - case IResource::Type::Texture2D: - textureType = isArray ? MTL::TextureType2DArray : MTL::TextureType2D; - break; - case IResource::Type::Texture3D: + const ITextureResource::Desc& textureDesc = *textureImpl->getDesc(); + SubresourceRange sr = desc.subresourceRange; + sr.mipLevelCount = sr.mipLevelCount == 0 ? textureDesc.numMipLevels - sr.mipLevel : sr.mipLevelCount; + sr.layerCount = sr.layerCount == 0 ? textureDesc.arraySize - sr.baseArrayLayer : sr.layerCount; + if (sr.mipLevel == 0 && sr.mipLevelCount == textureDesc.numMipLevels && + sr.baseArrayLayer == 0 && sr.layerCount == textureDesc.arraySize) { - if (isArray) SLANG_UNIMPLEMENTED_X("Metal does not support arrays of 3D textures."); - textureType = MTL::TextureType3D; - break; - } - case IResource::Type::TextureCube: - textureType = isArray ? MTL::TextureTypeCube : MTL::TextureTypeCubeArray; - break; - default: - SLANG_UNIMPLEMENTED_X("Unsupported texture type."); - break; + viewImpl->m_textureView = textureImpl->m_texture; + returnComPtr(outView, viewImpl); + return SLANG_OK; } - ITextureResource::Desc newDesc = *texture->getDesc(); - newDesc.numMipLevels = levelRange.length; - newDesc.arraySize = sliceRange.length; - view->m_type = ResourceViewImpl::ViewType::Texture; - view->m_texture = resourceImpl; //new TextureResourceImpl(newDesc, this); - view->m_texture->m_texture = NS::TransferPtr(resourceImpl->m_texture->newTextureView(pixelFormat, textureType, levelRange, sliceRange)); - returnComPtr(outView, view); + MTL::PixelFormat pixelFormat = desc.format == Format::Unknown ? textureImpl->m_pixelFormat : MetalUtil::translatePixelFormat(desc.format); + NS::Range levelRange(sr.baseArrayLayer, sr.layerCount); + NS::Range sliceRange(sr.mipLevel, sr.mipLevelCount); + viewImpl->m_textureView = NS::TransferPtr(textureImpl->m_texture->newTextureView(pixelFormat, textureImpl->m_textureType, levelRange, sliceRange)); + if (!viewImpl->m_textureView) + { + return SLANG_FAIL; + } + + returnComPtr(outView, viewImpl); return SLANG_OK; } diff --git a/tools/gfx/metal/metal-pipeline-state.cpp b/tools/gfx/metal/metal-pipeline-state.cpp index 8daaeccda..b23aab2b9 100644 --- a/tools/gfx/metal/metal-pipeline-state.cpp +++ b/tools/gfx/metal/metal-pipeline-state.cpp @@ -212,7 +212,18 @@ Result PipelineStateImpl::ensureAPIPipelineStateCreated() SLANG_NO_THROW Result SLANG_MCALL PipelineStateImpl::getNativeHandle(InteropHandle* outHandle) { - return SLANG_E_NOT_IMPLEMENTED; + switch (desc.type) + { + case PipelineType::Compute: + outHandle->api = InteropHandleAPI::Metal; + outHandle->handleValue = reinterpret_cast<intptr_t>(m_computePipelineState.get()); + return SLANG_OK; + case PipelineType::Graphics: + outHandle->api = InteropHandleAPI::Metal; + outHandle->handleValue = reinterpret_cast<intptr_t>(m_renderPipelineState.get()); + return SLANG_OK; + } + return SLANG_FAIL; } RayTracingPipelineStateImpl::RayTracingPipelineStateImpl(DeviceImpl* device) diff --git a/tools/gfx/metal/metal-resource-views.h b/tools/gfx/metal/metal-resource-views.h index 9a8e24ab5..89986f19d 100644 --- a/tools/gfx/metal/metal-resource-views.h +++ b/tools/gfx/metal/metal-resource-views.h @@ -41,6 +41,7 @@ public: {} ~TextureResourceViewImpl(); RefPtr<TextureResourceImpl> m_texture; + NS::SharedPtr<MTL::Texture> m_textureView; virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) override; }; diff --git a/tools/gfx/metal/metal-shader-object.cpp b/tools/gfx/metal/metal-shader-object.cpp index fde04f9ba..33e19bc6f 100644 --- a/tools/gfx/metal/metal-shader-object.cpp +++ b/tools/gfx/metal/metal-shader-object.cpp @@ -388,7 +388,7 @@ Result ShaderObjectImpl::bindAsValue( for (uint32_t i = 0; i < count; ++i) { auto texture = m_textures[baseIndex + i]; - context->setTexture(texture ? texture->m_texture->m_texture.get() : nullptr, registerOffset + i); + context->setTexture(texture ? texture->m_textureView.get() : nullptr, registerOffset + i); } } diff --git a/tools/gfx/metal/metal-texture.h b/tools/gfx/metal/metal-texture.h index 8f8ab3576..aff49beb6 100644 --- a/tools/gfx/metal/metal-texture.h +++ b/tools/gfx/metal/metal-texture.h @@ -22,9 +22,8 @@ public: BreakableReference<DeviceImpl> m_device; NS::SharedPtr<MTL::Texture> m_texture; - // TODO still needed? - // MTL::PixelFormat m_metalFormat = MTL::PixelFormat::PixelFormatInvalid; - // bool m_isWeakImageReference = false; + MTL::TextureType m_textureType; + MTL::PixelFormat m_pixelFormat; virtual SLANG_NO_THROW Result SLANG_MCALL getNativeResourceHandle(InteropHandle* outHandle) override; |
