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/gfx/metal/metal-device.cpp | |
| parent | df0a201d85eac4c55c1abf15ed0bf9baea0ae971 (diff) | |
[gfx] Metal texture fixes (#4331)
Diffstat (limited to 'tools/gfx/metal/metal-device.cpp')
| -rw-r--r-- | tools/gfx/metal/metal-device.cpp | 125 |
1 files changed, 81 insertions, 44 deletions
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; } |
