Skip to content

Commit

Permalink
Fixes to attachment and image clearing to pass CTS tests.
Browse files Browse the repository at this point in the history
MVKCmdClearAttachments support clearing multiple attachment layers.
MVKCmdClearImage use renderpass clear, and support clearning multiple image layers.
Rename mvkCmdClearImage() to mvkCmdClearColorImage().
MVKDevice add getFormatIsSupported() to allow devices to test for format support.
MVKFramebuffer support multiple layers.
mvk_datatypes.h support both 2D and 3D mipmap calculations and allow
mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology() in iOS.
Remove support for VK_FORMAT_B10G11R11_UFLOAT_PACK32 & VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
since format components are reversed on Metal.
Move OS extension source files to new OS directory.
Update to latest SPIRV-Cross version.
Update MoltenVK version to 1.0.16.
  • Loading branch information
billhollings committed Jul 24, 2018
1 parent 40df55a commit 2d4de6d
Show file tree
Hide file tree
Showing 36 changed files with 512 additions and 282 deletions.
21 changes: 13 additions & 8 deletions Docs/MoltenVK_Runtime_UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,21 @@ About **MoltenVK**
graphics and compute API, that runs on Apple's [*Metal*](https://developer.apple.com/metal)
graphics and compute framework on both *iOS* and *macOS*.

**MoltenVK** allows you to use the *Vulkan* graphics and compute API to develop modern, cross-platform,
high-performance graphical games and applications, and to run them across many platforms, including
both *iOS* and *macOS*.
**MoltenVK** allows you to use the *Vulkan* graphics and compute API to develop modern,
cross-platform, high-performance graphical games and applications, and to run them across
many platforms, including both *iOS* and *macOS*.

*Metal* uses a different shading language, the *Metal Shading Language (MSL)*, than
*Vulkan*, which uses *SPIR-V*. However, fear not, as **MoltenVK** will automatically convert
your *SPIR-V* shaders to their *MSL* equivalents. This can be performed transparently at run time,
using the **Runtime Shader Conversion** feature of **MoltenVK**, or at development time using the
[**MoltenVKShaderConverter**](#shader_converter_tool) tool provided with this **MoltenVK** distribution
package.
*Vulkan*, which uses *SPIR-V*. **MoltenVK** automatically converts your *SPIR-V* shaders
to their *MSL* equivalents. This can be performed transparently at run time, using the
**Runtime Shader Conversion** feature of **MoltenVK**, or at development time using the
[**MoltenVKShaderConverter**] (#shader_converter_tool) tool provided with this **MoltenVK**
distribution package.

To provide *Vulkan* capability to the *iOS* and *macOS* platforms, **MoltenVK** uses *Apple's*
publicly available API's, including *Metal*. **MoltenVK** does **_not_** use any private or
undocumented API calls or features, so your app will be compatible with all standard distribution
channels, including *Apple's App Store*.


<a name="install"></a>
Expand Down
2 changes: 1 addition & 1 deletion ExternalRevisions/SPIRV-Cross_repo_revision
Original file line number Diff line number Diff line change
@@ -1 +1 @@
be7425ef70231ab82930331959ab487d605d0482
cc7679ee4586a2e19cb6277fe40228b03d191760
152 changes: 92 additions & 60 deletions MoltenVK/MoltenVK.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

26 changes: 20 additions & 6 deletions MoltenVK/MoltenVK/API/mvk_datatypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,25 @@ uint32_t mvkMipmapLevels3D(VkExtent3D extent);
* Returns the size of the specified zero-based mipmap level,
* when the size of the base level is the specified size.
*/
VkExtent2D mvkMipmapLevelSizeFromBaseSize(VkExtent2D baseSize, uint32_t level);
VkExtent2D mvkMipmapLevelSizeFromBaseSize2D(VkExtent2D baseSize, uint32_t level);

/**
* Returns the size of the specified zero-based mipmap level,
* when the size of the base level is the specified size.
*/
VkExtent3D mvkMipmapLevelSizeFromBaseSize3D(VkExtent3D baseSize, uint32_t level);

/**
* Returns the size of the mipmap base level, when the size of
* the specified zero-based mipmap level is the specified size.
*/
VkExtent2D mvkMipmapBaseSizeFromLevelSize(VkExtent2D levelSize, uint32_t level);
VkExtent2D mvkMipmapBaseSizeFromLevelSize2D(VkExtent2D levelSize, uint32_t level);

/**
* Returns the size of the mipmap base level, when the size of
* the specified zero-based mipmap level is the specified size.
*/
VkExtent3D mvkMipmapBaseSizeFromLevelSize3D(VkExtent3D levelSize, uint32_t level);


#pragma mark Samplers
Expand Down Expand Up @@ -319,10 +331,12 @@ MTLVertexStepFunction mvkMTLVertexStepFunctionFromVkVertexInputRate(VkVertexInpu
/** Returns the Metal MTLPrimitiveType corresponding to the specified Vulkan VkPrimitiveTopology. */
MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology);

#if MVK_MACOS
/** Returns the Metal MTLPrimitiveTopologyClass corresponding to the specified Vulkan VkPrimitiveTopology. */
MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology);
#endif
/**
* Returns the Metal MTLPrimitiveTopologyClass corresponding to the specified Vulkan VkPrimitiveTopology.
*
* The value is treated as an NSUInteger to support OS versions on which the enum is unavailable.
*/
NSUInteger mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology);

/** Returns the Metal MTLLoadAction corresponding to the specified Vulkan VkAttachmentLoadOp. */
MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachmentLoadOp vkLoadOp);
Expand Down
2 changes: 1 addition & 1 deletion MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ extern "C" {
*/
#define MVK_VERSION_MAJOR 1
#define MVK_VERSION_MINOR 0
#define MVK_VERSION_PATCH 15
#define MVK_VERSION_PATCH 16

#define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch))
#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH)
Expand Down
20 changes: 10 additions & 10 deletions MoltenVK/MoltenVK/Commands/MVKCmdTransfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ class MVKCmdClearAttachments : public MVKCommand {
void populateVertices(VkClearRect& clearRect, float attWidth, float attHeight);

std::vector<VkClearRect> _clearRects;
std::vector<simd::float2> _vertices;
std::vector<simd::float4> _vertices;
simd::float4 _clearColors[kMVKAttachmentFormatCount];
VkClearValue _vkClearValues[kMVKAttachmentFormatCount];
MVKRPSKeyClearAtt _rpsKey;
Expand Down Expand Up @@ -279,9 +279,9 @@ class MVKCmdClearImage : public MVKCommand {
MVKImage* _image;
VkImageLayout _imgLayout;
std::vector<VkImageSubresourceRange> _subresourceRanges;
simd::float4 _clearColors[kMVKAttachmentFormatCount];
MVKRPSKeyClearAtt _rpsKey;
uint32_t _mtlStencilValue;
MTLClearColor _mtlColorClearValue;
double _mtlDepthClearValue;
uint32_t _mtlStencilClearValue;
bool _isDepthStencilClear;
};

Expand Down Expand Up @@ -396,12 +396,12 @@ void mvkCmdClearAttachments(MVKCommandBuffer* cmdBuff,
const VkClearRect* pRects);

/** Adds a clear color image command to the specified command buffer. */
void mvkCmdClearImage(MVKCommandBuffer* cmdBuff,
VkImage image,
VkImageLayout imageLayout,
const VkClearColorValue* pColor,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges);
void mvkCmdClearColorImage(MVKCommandBuffer* cmdBuff,
VkImage image,
VkImageLayout imageLayout,
const VkClearColorValue* pColor,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges);

/** Adds a clear depth stencil image command to the specified command buffer. */
void mvkCmdClearDepthStencilImage(MVKCommandBuffer* cmdBuff,
Expand Down
177 changes: 75 additions & 102 deletions MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "MVKBuffer.h"
#include "MVKFramebuffer.h"
#include "MVKRenderPass.h"
#include "MTLRenderPassDescriptor+MoltenVK.h"
#include "mvk_datatypes.h"


Expand Down Expand Up @@ -774,35 +775,43 @@
bottomPos = (bottomPos * 2.0) - 1.0;
topPos = (topPos * 2.0) - 1.0;

simd::float2 vtx;
simd::float4 vtx;

// Top left vertex - First triangle
vtx.y = topPos;
vtx.x = leftPos;
_vertices.push_back(vtx);
uint32_t startLayer = clearRect.baseArrayLayer;
uint32_t endLayer = startLayer + clearRect.layerCount;
for (uint32_t layer = startLayer; layer < endLayer; layer++) {

// Bottom left vertex
vtx.y = bottomPos;
vtx.x = leftPos;
_vertices.push_back(vtx);
vtx.z = 0.0;
vtx.w = layer;

// Bottom right vertex
vtx.y = bottomPos;
vtx.x = rightPos;
_vertices.push_back(vtx);
// Top left vertex - First triangle
vtx.y = topPos;
vtx.x = leftPos;
_vertices.push_back(vtx);

// Bottom right vertex - Second triangle
_vertices.push_back(vtx);
// Bottom left vertex
vtx.y = bottomPos;
vtx.x = leftPos;
_vertices.push_back(vtx);

// Top right vertex
vtx.y = topPos;
vtx.x = rightPos;
_vertices.push_back(vtx);
// Bottom right vertex
vtx.y = bottomPos;
vtx.x = rightPos;
_vertices.push_back(vtx);

// Top left vertex
vtx.y = topPos;
vtx.x = leftPos;
_vertices.push_back(vtx);
// Bottom right vertex - Second triangle
_vertices.push_back(vtx);

// Top right vertex
vtx.y = topPos;
vtx.x = rightPos;
_vertices.push_back(vtx);

// Top left vertex
vtx.y = topPos;
vtx.x = leftPos;
_vertices.push_back(vtx);
}
}

void MVKCmdClearAttachments::encode(MVKCommandEncoder* cmdEncoder) {
Expand Down Expand Up @@ -840,7 +849,7 @@

cmdEncoder->setVertexBytes(mtlRendEnc, _clearColors, sizeof(_clearColors), 0);
cmdEncoder->setFragmentBytes(mtlRendEnc, _clearColors, sizeof(_clearColors), 0);
cmdEncoder->setVertexBytes(mtlRendEnc, _vertices.data(), vtxCnt * sizeof(simd::float2), vtxBuffIdx);
cmdEncoder->setVertexBytes(mtlRendEnc, _vertices.data(), vtxCnt * sizeof(_vertices[0]), vtxBuffIdx);
[mtlRendEnc drawPrimitives: MTLPrimitiveTypeTriangle vertexStart: 0 vertexCount: vtxCnt];
[mtlRendEnc popDebugGroup];
}
Expand All @@ -858,23 +867,10 @@
_image = (MVKImage*)image;
_imgLayout = imageLayout;
_isDepthStencilClear = isDepthStencilClear;
_mtlStencilValue = 0;

_rpsKey = kMVKRPSKeyClearAttDefault;
_rpsKey.mtlSampleCount = _image->getSampleCount();

if (_isDepthStencilClear) {
_rpsKey.enable(kMVKAttachmentFormatDepthStencilIndex);
_rpsKey.attachmentMTLPixelFormats[kMVKAttachmentFormatDepthStencilIndex] = _image->getMTLPixelFormat();
float mtlDepthVal = mvkMTLClearDepthFromVkClearValue(clearValue);
_clearColors[kMVKAttachmentFormatDepthStencilIndex] = { mtlDepthVal, mtlDepthVal, mtlDepthVal, mtlDepthVal };
_mtlStencilValue = mvkMTLClearStencilFromVkClearValue(clearValue);
} else {
_rpsKey.enable(0);
_rpsKey.attachmentMTLPixelFormats[0] = _image->getMTLPixelFormat();
MTLClearColor mtlCC = mvkMTLClearColorFromVkClearValue(clearValue, _image->getVkFormat());
_clearColors[0] = { (float)mtlCC.red, (float)mtlCC.green, (float)mtlCC.blue, (float)mtlCC.alpha};
}

_mtlColorClearValue = mvkMTLClearColorFromVkClearValue(clearValue, _image->getVkFormat());
_mtlDepthClearValue = mvkMTLClearDepthFromVkClearValue(clearValue);
_mtlStencilClearValue = mvkMTLClearStencilFromVkClearValue(clearValue);

// Add subresource ranges
_subresourceRanges.clear();
Expand All @@ -883,64 +879,51 @@
_subresourceRanges.push_back(pRanges[i]);
}
}

void MVKCmdClearImage::encode(MVKCommandEncoder* cmdEncoder) {

MTLPixelFormat imgMTLPixFmt = _image->getMTLPixelFormat();
id<MTLTexture> imgMTLTex = _image->getMTLTexture();
id<MTLTexture> imgMTLTex = _image->getMTLTexture();
if ( !imgMTLTex ) { return; }

cmdEncoder->endCurrentMetalEncoding();
VkExtent3D imgBaseExtent = _image->getExtent3D();
NSString* mtlRendEncName = (_isDepthStencilClear
? mvkMTLRenderCommandEncoderLabel(kMVKCommandUseClearDepthStencilImage)
: mvkMTLRenderCommandEncoderLabel(kMVKCommandUseClearColorImage));

static const simd::float2 vertices[] = {
{ -1.0, -1.0 }, // Bottom-left
{ 1.0, -1.0 }, // Bottom-right
{ -1.0, 1.0 }, // Top-left
{ 1.0, 1.0 }, // Top-right
};
cmdEncoder->endCurrentMetalEncoding();

uint32_t vtxBuffIdx = getDevice()->getMetalBufferIndexForVertexAttributeBinding(kMVKVertexContentBufferIndex);
for (auto& srRange : _subresourceRanges) {

MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor];
MTLRenderPassColorAttachmentDescriptor* mtlRPCADesc = nil;
MTLRenderPassDepthAttachmentDescriptor* mtlRPDADesc = nil;
MTLRenderPassStencilAttachmentDescriptor* mtlRPSADesc = nil;

MTLRenderPassDescriptor* mtlRPDesc = [MTLRenderPassDescriptor renderPassDescriptor];
MTLRenderPassAttachmentDescriptor* mtlRPCADesc = nil;
MTLRenderPassAttachmentDescriptor* mtlRPDADesc = nil;
MTLRenderPassAttachmentDescriptor* mtlRPSADesc = nil;
NSString* mtlRendEncName;
NSString* mtlDebugGroupName;
if (_isDepthStencilClear) {
if (mvkMTLPixelFormatIsDepthFormat(imgMTLPixFmt)) {
bool isClearingColor = !_isDepthStencilClear && mvkIsAnyFlagEnabled(srRange.aspectMask, VK_IMAGE_ASPECT_COLOR_BIT);
bool isClearingDepth = _isDepthStencilClear && mvkIsAnyFlagEnabled(srRange.aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT);
bool isClearingStencil = _isDepthStencilClear && mvkIsAnyFlagEnabled(srRange.aspectMask, VK_IMAGE_ASPECT_STENCIL_BIT);

if (isClearingColor) {
mtlRPCADesc = mtlRPDesc.colorAttachments[0];
mtlRPCADesc.texture = imgMTLTex;
mtlRPCADesc.loadAction = MTLLoadActionClear;
mtlRPCADesc.storeAction = MTLStoreActionStore;
mtlRPCADesc.clearColor = _mtlColorClearValue;
}

if (isClearingDepth) {
mtlRPDADesc = mtlRPDesc.depthAttachment;
mtlRPDADesc.texture = imgMTLTex;
mtlRPDADesc.loadAction = MTLLoadActionLoad;
mtlRPDADesc.loadAction = MTLLoadActionClear;
mtlRPDADesc.storeAction = MTLStoreActionStore;
mtlRPDADesc.clearDepth = _mtlDepthClearValue;
}
if (mvkMTLPixelFormatIsStencilFormat(imgMTLPixFmt)) {

if (isClearingStencil) {
mtlRPSADesc = mtlRPDesc.stencilAttachment;
mtlRPSADesc.texture = imgMTLTex;
mtlRPSADesc.loadAction = MTLLoadActionLoad;
mtlRPSADesc.loadAction = MTLLoadActionClear;
mtlRPSADesc.storeAction = MTLStoreActionStore;
mtlRPSADesc.clearStencil = _mtlStencilClearValue;
}
mtlDebugGroupName = @"vkCmdClearDepthStencilImage";
mtlRendEncName = mvkMTLRenderCommandEncoderLabel(kMVKCommandUseClearDepthStencilImage);
} else {
mtlRPCADesc = mtlRPDesc.colorAttachments[0];
mtlRPCADesc.texture = imgMTLTex;
mtlRPCADesc.loadAction = MTLLoadActionLoad;
mtlRPCADesc.storeAction = MTLStoreActionStore;
mtlDebugGroupName = @"vkCmdClearColorImage";
mtlRendEncName = mvkMTLRenderCommandEncoderLabel(kMVKCommandUseClearColorImage);
}

MVKCommandEncodingPool* cmdEncPool = cmdEncoder->getCommandEncodingPool();
id<MTLRenderPipelineState> mtlRPS = cmdEncPool->getCmdClearMTLRenderPipelineState(_rpsKey);

size_t srCnt = _subresourceRanges.size();
for (uint32_t srIdx = 0; srIdx < srCnt; srIdx++) {
auto& srRange = _subresourceRanges[srIdx];

bool isClearingDepth = _isDepthStencilClear && mvkIsAnyFlagEnabled(srRange.aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT);
bool isClearingStencil = _isDepthStencilClear && mvkIsAnyFlagEnabled(srRange.aspectMask, VK_IMAGE_ASPECT_STENCIL_BIT);
id<MTLDepthStencilState> mtlDSS = cmdEncPool->getMTLDepthStencilState(isClearingDepth, isClearingStencil);

// Extract the mipmap levels that are to be updated
uint32_t mipLvlStart = srRange.baseMipLevel;
Expand All @@ -961,6 +944,7 @@
mtlRPCADesc.level = mipLvl;
mtlRPDADesc.level = mipLvl;
mtlRPSADesc.level = mipLvl;
mtlRPDesc.renderTargetArrayLengthMVK = mvkMipmapLevelSizeFromBaseSize3D(imgBaseExtent, mipLvl).depth;

for (uint32_t layer = layerStart; layer < layerEnd; layer++) {
mtlRPCADesc.slice = layer;
Expand All @@ -969,17 +953,6 @@

id<MTLRenderCommandEncoder> mtlRendEnc = [cmdEncoder->_mtlCmdBuffer renderCommandEncoderWithDescriptor: mtlRPDesc];
mtlRendEnc.label = mtlRendEncName;

[mtlRendEnc pushDebugGroup: mtlDebugGroupName];
[mtlRendEnc setRenderPipelineState: mtlRPS];
[mtlRendEnc setDepthStencilState: mtlDSS];
[mtlRendEnc setStencilReferenceValue: _mtlStencilValue];

cmdEncoder->setVertexBytes(mtlRendEnc, _clearColors, sizeof(_clearColors), 0);
cmdEncoder->setFragmentBytes(mtlRendEnc, _clearColors, sizeof(_clearColors), 0);
cmdEncoder->setVertexBytes(mtlRendEnc, vertices, sizeof(vertices), vtxBuffIdx);
[mtlRendEnc drawPrimitives: MTLPrimitiveTypeTriangleStrip vertexStart: 0 vertexCount: kMVKBlitVertexCount];
[mtlRendEnc popDebugGroup];
[mtlRendEnc endEncoding];
}
}
Expand Down Expand Up @@ -1138,12 +1111,12 @@ void mvkCmdClearAttachments(MVKCommandBuffer* cmdBuff,
cmdBuff->addCommand(cmd);
}

void mvkCmdClearImage(MVKCommandBuffer* cmdBuff,
VkImage image,
VkImageLayout imageLayout,
const VkClearColorValue* pColor,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges) {
void mvkCmdClearColorImage(MVKCommandBuffer* cmdBuff,
VkImage image,
VkImageLayout imageLayout,
const VkClearColorValue* pColor,
uint32_t rangeCount,
const VkImageSubresourceRange* pRanges) {
MVKCmdClearImage* cmd = cmdBuff->_commandPool->_cmdClearImagePool.acquireObject();
VkClearValue clrVal;
clrVal.color = *pColor;
Expand Down
Loading

0 comments on commit 2d4de6d

Please sign in to comment.