Skip to content

Commit

Permalink
Merge pull request #199 from billhollings/master
Browse files Browse the repository at this point in the history
Fixes to attachment and image clearing to pass CTS tests.
  • Loading branch information
billhollings authored Jul 24, 2018
2 parents 40df55a + 2d4de6d commit 16d8a04
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 16d8a04

Please sign in to comment.