Merge pull request #140 from billhollings/master

Clearing multisampled textures + minor fix to depth clip mode handling.
This commit is contained in:
Bill Hollings 2018-04-21 10:00:54 -04:00 committed by GitHub
commit 4b5aca57af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 74 additions and 51 deletions

View File

@ -708,7 +708,7 @@ void MVKCmdClearAttachments::setContent(uint32_t attachmentCount,
const VkClearAttachment* pAttachments,
uint32_t rectCount,
const VkClearRect* pRects) {
_rpsKey.reset();
_rpsKey = kMVKRPSKeyClearAttDefault;
_mtlStencilValue = 0;
_isClearingDepth = false;
_isClearingStencil = false;
@ -814,11 +814,11 @@ void MVKCmdClearAttachments::encode(MVKCommandEncoder* cmdEncoder) {
VkExtent2D fbExtent = cmdEncoder->_framebuffer->getExtent2D();
populateVertices(fbExtent.width, fbExtent.height);
uint32_t vtxCnt = (uint32_t)_vertices.size();
uint32_t vtxBuffIdx = getDevice()->getMetalBufferIndexForVertexAttributeBinding(kMVKVertexContentBufferIndex);
// Populate the render pipeline state attachment key with
// the format of each color attachment used by the subpass
// Populate the render pipeline state attachment key with attachment info from the subpass.
_rpsKey.mtlSampleCount = mvkSampleCountFromVkSampleCountFlagBits(subpass->getSampleCount());
uint32_t caCnt = subpass->getColorAttachmentCount();
for (uint32_t caIdx = 0; caIdx < caCnt; caIdx++) {
VkFormat vkAttFmt = subpass->getColorAttachmentFormat(caIdx);
@ -868,9 +868,10 @@ void MVKCmdClearImage::setContent(VkImage image,
_image = (MVKImage*)image;
_imgLayout = imageLayout;
_isDepthStencilClear = isDepthStencilClear;
_mtlStencilValue = 0;
_rpsKey.reset();
_mtlStencilValue = 0;
_rpsKey = kMVKRPSKeyClearAttDefault;
_rpsKey.mtlSampleCount = _image->getSampleCount();
if (_isDepthStencilClear) {
_rpsKey.enable(kMVKAttachmentFormatDepthStencilIndex);

View File

@ -167,8 +167,6 @@ void MVKDepthStencilCommandEncoderState:: setDepthStencilState(VkPipelineDepthSt
setStencilState(_depthStencilData.frontFaceStencilData, vkDepthStencilInfo.front, vkDepthStencilInfo.stencilTestEnable);
setStencilState(_depthStencilData.backFaceStencilData, vkDepthStencilInfo.back, vkDepthStencilInfo.stencilTestEnable);
_depthStencilData.clearHash(); // Hash will change
markDirty();
}

View File

@ -20,6 +20,7 @@
#include "MVKDevice.h"
#include "MVKFoundation.h"
#include "mvk_datatypes.h"
#include <string>
#import <Metal/Metal.h>
@ -33,13 +34,16 @@
/**
* Key to use for looking up cached MTLRenderPipelineState instances.
* Holds the formats for each color attachment plus one depth/stencil attachment.
* Indicates which attachments are used, and holds the Metal pixel formats for each
* color attachment plus one depth/stencil attachment. Also holds the Metal sample count.
*
* This structure can be used as a key in a std::map and std::unordered_map.
*/
typedef struct MVKRPSKeyClearAtt_t {
uint16_t attachmentMTLPixelFormats[kMVKAttachmentFormatCount];
uint16_t mtlSampleCount;
uint32_t enabledFlags;
const static uint32_t bitFlag = 1;
void enable(uint32_t attIdx) { mvkEnableFlag(enabledFlags, bitFlag << attIdx); }
@ -55,14 +59,26 @@ typedef struct MVKRPSKeyClearAtt_t {
bool operator==(const MVKRPSKeyClearAtt_t& rhs) const {
return ((enabledFlags == rhs.enabledFlags) &&
(mtlSampleCount == rhs.mtlSampleCount) &&
(memcmp(attachmentMTLPixelFormats, rhs.attachmentMTLPixelFormats, sizeof(attachmentMTLPixelFormats)) == 0));
}
void reset() { memset(this, 0, sizeof(*this)); }
std::size_t hash() const {
std::size_t hash = mvkHash(&enabledFlags);
hash = mvkHash(&mtlSampleCount, 1, hash);
return mvkHash(attachmentMTLPixelFormats, kMVKAttachmentFormatCount, hash);
}
MVKRPSKeyClearAtt_t() {
memset(this, 0, sizeof(*this));
mtlSampleCount = mvkSampleCountFromVkSampleCountFlagBits(VK_SAMPLE_COUNT_1_BIT);
}
MVKRPSKeyClearAtt_t() { reset(); }
} MVKRPSKeyClearAtt;
/** An instance populated with default values, for use in resetting other instances to default state. */
const MVKRPSKeyClearAtt kMVKRPSKeyClearAttDefault;
/**
* Hash structure implementation for MVKRPSKeyClearAtt in std namespace,
* so MVKRPSKeyClearAtt can be used as a key in a std::map and std::unordered_map.
@ -70,10 +86,7 @@ typedef struct MVKRPSKeyClearAtt_t {
namespace std {
template <>
struct hash<MVKRPSKeyClearAtt> {
std::size_t operator()(const MVKRPSKeyClearAtt& k) const {
std::size_t hash = mvkHash(&k.enabledFlags, 1);
return mvkHash(k.attachmentMTLPixelFormats, kMVKAttachmentFormatCount, hash);
}
std::size_t operator()(const MVKRPSKeyClearAtt& k) const { return k.hash(); }
};
}
@ -126,29 +139,18 @@ const MVKMTLStencilDescriptorData kMVKMTLStencilDescriptorDataDefault;
* change as early as possible.
*/
typedef struct MVKMTLDepthStencilDescriptorData_t {
std::size_t _hash;
uint8_t depthCompareFunction; /**< The depth compare function (interpreted as MTLCompareFunction). */
bool depthWriteEnabled; /**< Indicates whether depth writing is enabled. */
MVKMTLStencilDescriptorData frontFaceStencilData;
MVKMTLStencilDescriptorData backFaceStencilData;
std::size_t hash() {
if ( !_hash ) { _hash = mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t)); }
return _hash;
}
void clearHash() { _hash = 0; }
bool operator==(const MVKMTLDepthStencilDescriptorData_t& rhs) const {
return (memcmp(this, &rhs, sizeof(*this)) == 0);
}
bool operator==(const MVKMTLDepthStencilDescriptorData_t& rhs) const {
MVKMTLDepthStencilDescriptorData_t* pLHS = (MVKMTLDepthStencilDescriptorData_t*)this;
MVKMTLDepthStencilDescriptorData_t* pRHS = (MVKMTLDepthStencilDescriptorData_t*)&rhs;
if (pLHS == pRHS) { return true; }
if (!pLHS) { return false; }
if (!pRHS) { return false; }
if (pLHS->hash() != pRHS->hash()) { return false; }
return (memcmp(pLHS, pRHS, sizeof(*this)) == 0);
}
std::size_t hash() const {
return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t));
}
MVKMTLDepthStencilDescriptorData_t() {
@ -156,7 +158,6 @@ typedef struct MVKMTLDepthStencilDescriptorData_t {
// even if the structure contains alignment gaps.
memset(this, 0, sizeof(*this));
_hash = 0;
depthCompareFunction = MTLCompareFunctionAlways;
depthWriteEnabled = false;
@ -171,11 +172,8 @@ const MVKMTLDepthStencilDescriptorData kMVKMTLDepthStencilDescriptorDataDefault;
namespace std {
template <>
struct hash<MVKMTLDepthStencilDescriptorData_t> {
std::size_t operator()(const MVKMTLDepthStencilDescriptorData_t& k) const {
MVKMTLDepthStencilDescriptorData_t* pK = (MVKMTLDepthStencilDescriptorData_t*)&k;
return pK->hash();
}
struct hash<MVKMTLDepthStencilDescriptorData> {
std::size_t operator()(const MVKMTLDepthStencilDescriptorData& k) const { return k.hash(); }
};
}
@ -202,6 +200,10 @@ typedef struct MVKImageDescriptorData_t {
return (memcmp(this, &rhs, sizeof(*this)) == 0);
}
std::size_t hash() const {
return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t));
}
MVKImageDescriptorData_t() { memset(this, 0, sizeof(*this)); }
} __attribute__((aligned(sizeof(uint64_t)))) MVKImageDescriptorData;
@ -213,9 +215,7 @@ typedef struct MVKImageDescriptorData_t {
namespace std {
template <>
struct hash<MVKImageDescriptorData> {
std::size_t operator()(const MVKImageDescriptorData& k) const {
return mvkHash((uint64_t*)this, sizeof(*this) / sizeof(uint64_t));
}
std::size_t operator()(const MVKImageDescriptorData& k) const { return k.hash(); }
};
}

View File

@ -97,6 +97,7 @@ id<MTLRenderPipelineState> MVKCommandResourceFactory::newCmdClearMTLRenderPipeli
plDesc.label = [NSString stringWithFormat: @"CmdClearAttachments%s", fragFuncSfx.data()];
plDesc.vertexFunction = getFunctionNamed("vtxCmdClearAttachments");
plDesc.fragmentFunction = getFunctionNamed((string("fragCmdClearAttachments") + fragFuncSfx).data());
plDesc.sampleCount = attKey.mtlSampleCount;
for (uint32_t caIdx = 0; caIdx < kMVKAttachmentFormatDepthStencilIndex; caIdx++) {
MTLRenderPipelineColorAttachmentDescriptor* colorDesc = plDesc.colorAttachments[caIdx];

View File

@ -330,8 +330,10 @@ void MVKPhysicalDevice::initMetalFeatures() {
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily1_v4] ) {
_metalFeatures.mslVersion = SPIRVToMSLConverterOptions::makeMSLVersion(2);
_metalFeatures.ioSurfaces = true;
_metalFeatures.depthClipMode = true;
}
if ( [_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily2_v4] ) {
_metalFeatures.depthClipMode = true;
}
#endif
#if MVK_MACOS
@ -358,7 +360,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
#endif
for (uint32_t sc = VK_SAMPLE_COUNT_1_BIT; sc <= VK_SAMPLE_COUNT_64_BIT; sc <<= 1) {
if ([_mtlDevice supportsTextureSampleCount: sc]) {
if ([_mtlDevice supportsTextureSampleCount: mvkSampleCountFromVkSampleCountFlagBits((VkSampleCountFlagBits)sc)]) {
_metalFeatures.supportedSampleCounts |= sc;
}
}

View File

@ -76,7 +76,7 @@ public:
inline uint32_t getLayerCount() { return _arrayLayers; }
/** Returns the number of samples for each pixel of this image. */
inline uint32_t getSampleCount() { return _samples; }
inline VkSampleCountFlagBits getSampleCount() { return _samples; }
/**
* Returns the number of bytes per image row at the specified zero-based mip level.

View File

@ -582,7 +582,7 @@ MVKImageView::MVKImageView(MVKDevice* device, const VkImageViewCreateInfo* pCrea
_mtlTexture = nil;
_mtlPixelFormat = getSwizzledMTLPixelFormat(pCreateInfo->format, pCreateInfo->components);
_mtlTextureType = mvkMTLTextureTypeFromVkImageViewType(pCreateInfo->viewType, (_image->getSampleCount() > 1));
_mtlTextureType = mvkMTLTextureTypeFromVkImageViewType(pCreateInfo->viewType, (_image->getSampleCount() != VK_SAMPLE_COUNT_1_BIT));
initMTLTextureViewSupport();
}

View File

@ -44,6 +44,9 @@ public:
/** Returns the format of the depth/stencil attachment. */
VkFormat getDepthStencilFormat();
/** Returns the Vulkan sample count of the attachments used in this subpass. */
VkSampleCountFlagBits getSampleCount();
/**
* Populates the specified Metal MTLRenderPassDescriptor with content from this
* instance, the specified framebuffer, and the specified array of clear values.
@ -92,6 +95,9 @@ public:
/** Returns the Vulkan format of this attachment. */
VkFormat getFormat();
/** Returns the Vulkan sample count of this attachment. */
VkSampleCountFlagBits getSampleCount();
/**
* Populates the specified Metal color attachment description with the load and store actions for
* the specified render subpass, and returns whether the load action will clear the attachment.

View File

@ -43,6 +43,21 @@ VkFormat MVKRenderSubpass::getDepthStencilFormat() {
return _renderPass->_attachments[rpAttIdx].getFormat();
}
VkSampleCountFlagBits MVKRenderSubpass::getSampleCount() {
for (auto& ca : _colorAttachments) {
uint32_t rpAttIdx = ca.attachment;
if (rpAttIdx != VK_ATTACHMENT_UNUSED) {
return _renderPass->_attachments[rpAttIdx].getSampleCount();
}
}
uint32_t rpAttIdx = _depthStencilAttachment.attachment;
if (rpAttIdx != VK_ATTACHMENT_UNUSED) {
return _renderPass->_attachments[rpAttIdx].getSampleCount();
}
return VK_SAMPLE_COUNT_1_BIT;
}
void MVKRenderSubpass::populateMTLRenderPassDescriptor(MTLRenderPassDescriptor* mtlRPDesc,
MVKFramebuffer* framebuffer,
vector<VkClearValue>& clearValues,
@ -192,6 +207,8 @@ MVKRenderSubpass::MVKRenderSubpass(MVKRenderPass* renderPass,
VkFormat MVKRenderPassAttachment::getFormat() { return _info.format; }
VkSampleCountFlagBits MVKRenderPassAttachment::getSampleCount() { return _info.samples; }
bool MVKRenderPassAttachment::populateMTLRenderPassAttachmentDescriptor(MTLRenderPassAttachmentDescriptor* mtlAttDesc,
MVKRenderSubpass* subpass,
bool isRenderingEntireAttachment,

View File

@ -131,9 +131,7 @@ typedef struct MVKShaderModuleKey_t {
namespace std {
template <>
struct hash<MVKShaderModuleKey> {
std::size_t operator()(const MVKShaderModuleKey& k) const {
return k.codeHash;
}
std::size_t operator()(const MVKShaderModuleKey& k) const { return k.codeHash; }
};
}

View File

@ -305,7 +305,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
size_t mslCodeLen = pCreateInfo->codeSize - hdrSize;
uint64_t startTime = _device->getPerformanceTimestamp();
codeHash = mvkHash(&magicNum, 1);
codeHash = mvkHash(&magicNum);
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.hashShaderCode, startTime);
@ -320,7 +320,7 @@ MVKShaderModule::MVKShaderModule(MVKDevice* device,
size_t mslCodeLen = pCreateInfo->codeSize - hdrSize;
uint64_t startTime = _device->getPerformanceTimestamp();
codeHash = mvkHash(&magicNum, 1);
codeHash = mvkHash(&magicNum);
codeHash = mvkHash(pMSLCode, mslCodeLen, codeHash);
_device->addShaderCompilationEventPerformance(_device->_shaderCompilationPerformance.hashShaderCode, startTime);

View File

@ -255,7 +255,7 @@ const T& mvkClamp(const T& val, const T& lower, const T& upper) {
* value returned by previous calls as the seed in subsequent calls.
*/
template<class N>
std::size_t mvkHash(const N* pVals, std::size_t count, std::size_t seed = 5381) {
std::size_t mvkHash(const N* pVals, std::size_t count = 1, std::size_t seed = 5381) {
std::size_t hash = seed;
for (std::size_t i = 0; i < count; i++) { hash = ((hash << 5) + hash) ^ pVals[i]; }
return hash;