From 61de11b370f3f6779e037f13019b483c7eba53b5 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Sat, 19 Sep 2020 12:31:59 -0500 Subject: [PATCH 1/3] MVKImage: Correct offset for texel buffers and heaps. For planes other than 0, we must add the offset of the first subresource, so the plane is at the correct place in memory. --- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index d314f1e2..e615c7fa 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -54,13 +54,13 @@ id MVKImagePlane::getMTLTexture() { } else if (memoryBinding->_mtlTexelBuffer) { _mtlTexture = [memoryBinding->_mtlTexelBuffer newTextureWithDescriptor: mtlTexDesc - offset: memoryBinding->_mtlTexelBufferOffset + offset: memoryBinding->_mtlTexelBufferOffset + _subresources[0].layout.offset bytesPerRow: _subresources[0].layout.rowPitch]; } else if (memoryBinding->_deviceMemory->getMTLHeap() && !_image->getIsDepthStencil()) { // Metal support for depth/stencil from heaps is flaky _mtlTexture = [memoryBinding->_deviceMemory->getMTLHeap() newTextureWithDescriptor: mtlTexDesc - offset: memoryBinding->getDeviceMemoryOffset()]; + offset: memoryBinding->getDeviceMemoryOffset() + _subresources[0].layout.offset]; if (_image->_isAliasable) { [_mtlTexture makeAliasable]; } } else { _mtlTexture = [_image->getMTLDevice() newTextureWithDescriptor: mtlTexDesc]; From 656935b5592791e0780967f70290a21081ba4b53 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Mon, 21 Sep 2020 01:03:29 -0500 Subject: [PATCH 2/3] MVKCmdClearImage: Use layered rendering when possible. --- MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm | 37 +++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm index 15e4b1f1..76964a0d 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm @@ -1345,20 +1345,41 @@ void MVKCmdClearImage::encode(MVKCommandEncoder* cmdEncoder) { layerEnd = layerStart + layerCnt; } - for (uint32_t layer = layerStart; layer < layerEnd; layer++) { + // If we can do layered rendering, I can clear all the layers at once. + if (cmdEncoder->getDevice()->_pMetalFeatures->layeredRendering && + (_image->getSampleCount() == VK_SAMPLE_COUNT_1_BIT || cmdEncoder->getDevice()->_pMetalFeatures->multisampleLayeredRendering)) { if (is3D) { - mtlRPCADesc.depthPlane = layer; - mtlRPDADesc.depthPlane = layer; - mtlRPSADesc.depthPlane = layer; + mtlRPCADesc.depthPlane = layerStart; + mtlRPDADesc.depthPlane = layerStart; + mtlRPSADesc.depthPlane = layerStart; } else { - mtlRPCADesc.slice = layer; - mtlRPDADesc.slice = layer; - mtlRPSADesc.slice = layer; + mtlRPCADesc.slice = layerStart; + mtlRPDADesc.slice = layerStart; + mtlRPSADesc.slice = layerStart; } + mtlRPDesc.renderTargetArrayLength = (layerCnt == VK_REMAINING_ARRAY_LAYERS + ? (_image->getLayerCount() - layerStart) + : layerCnt); id mtlRendEnc = [cmdEncoder->_mtlCmdBuffer renderCommandEncoderWithDescriptor: mtlRPDesc]; - setLabelIfNotNil(mtlRendEnc, mtlRendEncName); + setLabelIfNotNil(mtlRendEnc, mtlRendEncName); [mtlRendEnc endEncoding]; + } else { + for (uint32_t layer = layerStart; layer < layerEnd; layer++) { + if (is3D) { + mtlRPCADesc.depthPlane = layer; + mtlRPDADesc.depthPlane = layer; + mtlRPSADesc.depthPlane = layer; + } else { + mtlRPCADesc.slice = layer; + mtlRPDADesc.slice = layer; + mtlRPSADesc.slice = layer; + } + + id mtlRendEnc = [cmdEncoder->_mtlCmdBuffer renderCommandEncoderWithDescriptor: mtlRPDesc]; + setLabelIfNotNil(mtlRendEnc, mtlRendEncName); + [mtlRendEnc endEncoding]; + } } } } From 35fbda1caeee5e75f0ced9358998ba34f573fc68 Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Tue, 22 Sep 2020 20:31:21 -0500 Subject: [PATCH 3/3] MVKCmdClearAttachments: Account for the renderArea. When calculating the vertices, we need to use the render area's extent--but only if the implementation supports constraining the render area using `renderTargetWidth` and `renderTargetHeight`. Otherwise, the quad will be stretched and/or squashed because of the render area constraint. --- MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm index 76964a0d..56b7bf2e 100644 --- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm +++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm @@ -1130,6 +1130,15 @@ void MVKCmdClearAttachments::encode(MVKCommandEncoder* cmdEncoder) { simd::float4 clearColors[kMVKClearAttachmentCount]; VkExtent2D fbExtent = cmdEncoder->_framebuffer->getExtent2D(); + // I need to know if the 'renderTargetWidth' and 'renderTargetHeight' properties + // actually do something, but [MTLRenderPassDescriptor instancesRespondToSelector: @selector(renderTargetWidth)] + // returns NO even on systems that do support it. So we have to check an actual instance. + MTLRenderPassDescriptor* tempRPDesc = [MTLRenderPassDescriptor new]; // temp retain + if ([tempRPDesc respondsToSelector: @selector(renderTargetWidth)]) { + VkRect2D renderArea = cmdEncoder->clipToRenderArea({{0, 0}, fbExtent}); + fbExtent = {renderArea.offset.x + renderArea.extent.width, renderArea.offset.y + renderArea.extent.height}; + } + [tempRPDesc release]; // temp release populateVertices(cmdEncoder, vertices, fbExtent.width, fbExtent.height); MVKPixelFormats* pixFmts = cmdEncoder->getPixelFormats();