From 385b760770c68228cd63bcd94766e20102932592 Mon Sep 17 00:00:00 2001 From: saschawillems Date: Mon, 12 Sep 2016 19:53:39 +0200 Subject: [PATCH] Opaque sparse memory bindings for mip tails --- .../sparseresidency.frag | 2 +- .../sparseresidency.frag.spv | Bin 1652 -> 1676 bytes .../texturesparseresidency.cpp | 81 +++++++++++++----- 3 files changed, 59 insertions(+), 24 deletions(-) diff --git a/data/shaders/texturesparseresidency/sparseresidency.frag b/data/shaders/texturesparseresidency/sparseresidency.frag index 1eb60ff6..a415a0d1 100644 --- a/data/shaders/texturesparseresidency/sparseresidency.frag +++ b/data/shaders/texturesparseresidency/sparseresidency.frag @@ -18,7 +18,7 @@ layout (location = 0) out vec4 outFragColor; void main() { // Get residency code for current texel - int residencyCode = sparseTextureARB(samplerColor, inUV, outFragColor); + int residencyCode = sparseTextureARB(samplerColor, inUV, outFragColor, inLodBias); // Check if texel is resident bool texelResident = sparseTexelsResidentARB(residencyCode); diff --git a/data/shaders/texturesparseresidency/sparseresidency.frag.spv b/data/shaders/texturesparseresidency/sparseresidency.frag.spv index b23cf22d8823e0e1a7601604d17c3caf0f434cc3..477433919c753272f16b46cd304924df4fd0896d 100644 GIT binary patch literal 1676 zcmY+ESx*!}6ordrW^;0dXZlA}u>Zm_Gdtna8I0O_+XRWAH2TBc|-|LH%8QElHbewXJoO zqh%?zaueQ0~^&4MwPUY+z9g|ouwcpZ{*lrqA zQnZ+3Nwp2>{@5l#(}s=H{itb$;V;N1ey7{E@qW~fVnMf`x`Ob-Q4g10jnPT^GWJ^q zUCGrQg!QPo7x+ru?VXc9w8{I^u61`@6IOP%Es_M%Om|bhkzHDnlKutZt0?aHZ7s!= zTt9>GD6n6TY$N07ukH+5$EhO^R4sKZ$@p@-s5LVNQ_q5o56sMpnE8QoJ-L9H8+zsn z<~4xH0ZgAKr9!vpCf(aJtw>p1RmPcBVcr4;KO^n1YUbKw8byS^U{wffR3}y zXCk;K8Kwt(v%+KYoJU^h$K^Q-9zB?zz@eX%M^8QIr{t*>9zB?z!4aR4XD@q*gXtmM zf-rA@I@v#^EUwD4kDk$k9N)+=x>dzF@2CAI#K{$oyNFk1 za8LUN-7FR}4lQ+n(K4qc8Qf3BuFLcNQ4D@rwko4Htl2}Yw`9dyZwnV|T@j|%kLnQh z+>x;d9W@ar7kWtSx6bEo?%}>X##<=H(2xUX@&nHP*Q%5^u#s`@hh1y#VaD`~{_CgH lY2?nh2N{Pp*VQtPy>GJox3p$Idg8oKa%3*V{_3_J*+0(-e}Di0 literal 1652 zcmY+E>rWFw6vYSH@(|@AFA+tsDk4|`0WrP;B=$?=0~J4R)^<`>%Wku~jq=UE&40>A zV&eG?yJi`3bLX6UX70UnmzMgggU0mfZ^%40XKTXr3mb!9ksmPw4%Zv+8nq;C)wZ_R zQI47t&c(*0Dr=9O_(2FiA)A&h%XVasWV^C)okOR@+Le^Wm>)`5Hp8ag@b(V(y~K9? z*iWsO9Q!RBd(o%QwwWg9H3|h`+w1sYyXUv9x3#(6^_yRG&*1-ibWLKt)P75QvE4ML zqG++kih3JT{@5l#%ZAOb{Dh85;Q9=%FUed1@rr zwmiAu$pvPva5-kKMa*2mJNo)~JKlrEoxj9XP*^v$=QWBRUU_?hC&X;j9H zz|7&Yj2Ue7Ror{dYL5o~tuoQ;6&XA=Jy#XX0FF5CKPMy3B2G}J9@ z3x}3^!DyM+4H?`|#g^n*e-wjXl--l@2JG{mZfRfa>9#OE5oZ>6Wz6?uHoFz=IfIU# zh*Jx1MeMikCpUS>m&cfSF@}a5ywL+0=U=N+X3Y;b9L6FKv*gXFX+!3I+zXt3HXVmH e*FDTQ&c4a&-_oA*=!x?kQX_LA_E*_(sparseImageMemoryReqs.size / sparseImageMemoryReqs.alignment); std::vector sparseMemoryBinds(sparseBindsCount); + // Check if the format has a single mip tail for all layers or one mip tail for each layer + // The mip tail contains all mip levels > sparseMemoryReq.imageMipTailFirstLod + bool singleMipTail = sparseMemoryReq.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT; + // Sparse bindings for each mip level of all layers outside of the mip tail for (uint32_t layer = 0; layer < texture.layerCount; layer++) { + // sparseMemoryReq.imageMipTailFirstLod is the first mip level that's stored inside the mip tail for (uint32_t mipLevel = 0; mipLevel < sparseMemoryReq.imageMipTailFirstLod; mipLevel++) { VkExtent3D extent; @@ -396,14 +400,47 @@ public: } } - // Sparse binding for the mip tail (if present) containing the remaining mip levels - // The mip tail contains all mip levels > sparseMemoryReq.imageMipTailFirstLod - if ((sparseMemoryReq.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT) && (sparseMemoryReq.imageMipTailFirstLod < texture.mipLevels)) + // Check if format has one mip tail per layer + if ((!singleMipTail) && (sparseMemoryReq.imageMipTailFirstLod < texture.mipLevels)) { - //todo - } + // Allocate memory for the mip tail + VkMemoryAllocateInfo allocInfo = vkTools::initializers::memoryAllocateInfo(); + allocInfo.allocationSize = sparseMemoryReq.imageMipTailSize; + allocInfo.memoryTypeIndex = memoryTypeIndex; + + VkDeviceMemory deviceMemory; + VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &deviceMemory)); + + // (Opaque) sparse memory binding + VkSparseMemoryBind sparseMemoryBind{}; + sparseMemoryBind.resourceOffset = sparseMemoryReq.imageMipTailOffset + layer * sparseMemoryReq.imageMipTailStride; + sparseMemoryBind.size = sparseMemoryReq.imageMipTailSize; + sparseMemoryBind.memory = deviceMemory; + + texture.opaqueMemoryBinds.push_back(sparseMemoryBind); + } } // end layers and mips + // Check if format has one mip tail for all layers + if ((sparseMemoryReq.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT) && (sparseMemoryReq.imageMipTailFirstLod < texture.mipLevels)) + { + // Allocate memory for the mip tail + VkMemoryAllocateInfo allocInfo = vkTools::initializers::memoryAllocateInfo(); + allocInfo.allocationSize = sparseMemoryReq.imageMipTailSize; + allocInfo.memoryTypeIndex = memoryTypeIndex; + + VkDeviceMemory deviceMemory; + VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &deviceMemory)); + + // (Opaque) sparse memory binding + VkSparseMemoryBind sparseMemoryBind{}; + sparseMemoryBind.resourceOffset = sparseMemoryReq.imageMipTailOffset; + sparseMemoryBind.size = sparseMemoryReq.imageMipTailSize; + sparseMemoryBind.memory = deviceMemory; + + texture.opaqueMemoryBinds.push_back(sparseMemoryBind); + } + // Create signal semaphore for sparse binding VkSemaphoreCreateInfo semaphoreCreateInfo = vkTools::initializers::semaphoreCreateInfo(); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &bindSparseSemaphore)); @@ -442,21 +479,15 @@ public: sampler.magFilter = VK_FILTER_LINEAR; sampler.minFilter = VK_FILTER_LINEAR; sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; - sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; - sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; sampler.mipLodBias = 0.0f; sampler.compareOp = VK_COMPARE_OP_NEVER; sampler.minLod = 0.0f; - sampler.maxLod = (float)texture.mipLevels; - sampler.maxAnisotropy = 1.0; - sampler.anisotropyEnable = VK_FALSE; - if (vulkanDevice->features.samplerAnisotropy) - { - // Use max. level of anisotropy for this example - sampler.maxAnisotropy = vulkanDevice->properties.limits.maxSamplerAnisotropy; - sampler.anisotropyEnable = VK_TRUE; - } + sampler.maxLod = static_cast(texture.mipLevels); + sampler.anisotropyEnable = vulkanDevice->features.samplerAnisotropy; + sampler.maxAnisotropy = vulkanDevice->features.samplerAnisotropy ? vulkanDevice->properties.limits.maxSamplerAnisotropy : 1.0f; sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; VK_CHECK_RESULT(vkCreateSampler(device, &sampler, nullptr, &texture.sampler)); @@ -486,11 +517,15 @@ public: vkDestroyImageView(device, texture.view, nullptr); vkDestroyImage(device, texture.image, nullptr); vkDestroySampler(device, texture.sampler, nullptr); - //vkFreeMemory(device, texture.deviceMemory, nullptr); - // Sparse memory - for (auto residency : texture.residencyMemoryBinds) + // Release sparse image memory + for (auto residencyBind : texture.residencyMemoryBinds) { - vkFreeMemory(device, residency.memory, nullptr); + vkFreeMemory(device, residencyBind.memory, nullptr); + } + // Release sparse opqaue memory (mip tail) + for (auto opaqueBind : texture.opaqueMemoryBinds) + { + vkFreeMemory(device, opaqueBind.memory, nullptr); } }