diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm index 15e4b1f1..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(); @@ -1345,20 +1354,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]; + } } } } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index b99eef9f..7db5dfd0 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];