diff --git a/src/backend/CMakeLists.txt b/src/backend/CMakeLists.txt index 61dcc75262..5be8d19ea5 100644 --- a/src/backend/CMakeLists.txt +++ b/src/backend/CMakeLists.txt @@ -320,6 +320,8 @@ if (NXT_ENABLE_VULKAN) ${VULKAN_DIR}/RenderPassVk.h ${VULKAN_DIR}/RenderPipelineVk.cpp ${VULKAN_DIR}/RenderPipelineVk.h + ${VULKAN_DIR}/SamplerVk.cpp + ${VULKAN_DIR}/SamplerVk.h ${VULKAN_DIR}/ShaderModuleVk.cpp ${VULKAN_DIR}/ShaderModuleVk.h ${VULKAN_DIR}/SwapChainVk.cpp diff --git a/src/backend/vulkan/BindGroupVk.cpp b/src/backend/vulkan/BindGroupVk.cpp index f51dfd0a1d..257869ec2a 100644 --- a/src/backend/vulkan/BindGroupVk.cpp +++ b/src/backend/vulkan/BindGroupVk.cpp @@ -17,6 +17,7 @@ #include "BindGroupLayoutVk.h" #include "BufferVk.h" #include "FencedDeleter.h" +#include "SamplerVk.h" #include "VulkanBackend.h" namespace backend { namespace vulkan { @@ -62,6 +63,7 @@ namespace backend { namespace vulkan { uint32_t numWrites = 0; std::array writes; std::array writeBufferInfo; + std::array writeImageInfo; const auto& layoutInfo = GetLayout()->GetBindingInfo(); for (uint32_t bindingIndex : IterateBitSet(layoutInfo.mask)) { @@ -87,7 +89,12 @@ namespace backend { namespace vulkan { write.pBufferInfo = &writeBufferInfo[numWrites]; } break; - case nxt::BindingType::Sampler: + case nxt::BindingType::Sampler: { + Sampler* sampler = ToBackend(GetBindingAsSampler(bindingIndex)); + writeImageInfo[numWrites].sampler = sampler->GetHandle(); + write.pImageInfo = &writeImageInfo[numWrites]; + } break; + case nxt::BindingType::SampledTexture: default: UNREACHABLE(); diff --git a/src/backend/vulkan/FencedDeleter.cpp b/src/backend/vulkan/FencedDeleter.cpp index a7b9ab4bd0..1e2b7a01db 100644 --- a/src/backend/vulkan/FencedDeleter.cpp +++ b/src/backend/vulkan/FencedDeleter.cpp @@ -31,6 +31,7 @@ namespace backend { namespace vulkan { ASSERT(mPipelinesToDelete.Empty()); ASSERT(mPipelineLayoutsToDelete.Empty()); ASSERT(mRenderPassesToDelete.Empty()); + ASSERT(mSamplersToDelete.Empty()); ASSERT(mSemaphoresToDelete.Empty()); ASSERT(mShaderModulesToDelete.Empty()); ASSERT(mSurfacesToDelete.Empty()); @@ -73,6 +74,10 @@ namespace backend { namespace vulkan { mRenderPassesToDelete.Enqueue(renderPass, mDevice->GetSerial()); } + void FencedDeleter::DeleteWhenUnused(VkSampler sampler) { + mSamplersToDelete.Enqueue(sampler, mDevice->GetSerial()); + } + void FencedDeleter::DeleteWhenUnused(VkSemaphore semaphore) { mSemaphoresToDelete.Enqueue(semaphore, mDevice->GetSerial()); } @@ -158,6 +163,11 @@ namespace backend { namespace vulkan { mDevice->fn.DestroyDescriptorPool(vkDevice, pool, nullptr); } mDescriptorPoolsToDelete.ClearUpTo(completedSerial); + + for (VkSampler sampler : mSamplersToDelete.IterateUpTo(completedSerial)) { + mDevice->fn.DestroySampler(vkDevice, sampler, nullptr); + } + mSamplersToDelete.ClearUpTo(completedSerial); } }} // namespace backend::vulkan diff --git a/src/backend/vulkan/FencedDeleter.h b/src/backend/vulkan/FencedDeleter.h index 9d5b9fc546..c59338b66a 100644 --- a/src/backend/vulkan/FencedDeleter.h +++ b/src/backend/vulkan/FencedDeleter.h @@ -36,6 +36,7 @@ namespace backend { namespace vulkan { void DeleteWhenUnused(VkPipelineLayout layout); void DeleteWhenUnused(VkRenderPass renderPass); void DeleteWhenUnused(VkPipeline pipeline); + void DeleteWhenUnused(VkSampler sampler); void DeleteWhenUnused(VkSemaphore semaphore); void DeleteWhenUnused(VkShaderModule module); void DeleteWhenUnused(VkSurfaceKHR surface); @@ -54,6 +55,7 @@ namespace backend { namespace vulkan { SerialQueue mPipelinesToDelete; SerialQueue mPipelineLayoutsToDelete; SerialQueue mRenderPassesToDelete; + SerialQueue mSamplersToDelete; SerialQueue mSemaphoresToDelete; SerialQueue mShaderModulesToDelete; SerialQueue mSurfacesToDelete; diff --git a/src/backend/vulkan/GeneratedCodeIncludes.h b/src/backend/vulkan/GeneratedCodeIncludes.h index cbefa5b78c..41811f8050 100644 --- a/src/backend/vulkan/GeneratedCodeIncludes.h +++ b/src/backend/vulkan/GeneratedCodeIncludes.h @@ -23,6 +23,7 @@ #include "backend/vulkan/PipelineLayoutVk.h" #include "backend/vulkan/RenderPassVk.h" #include "backend/vulkan/RenderPipelineVk.h" +#include "backend/vulkan/SamplerVk.h" #include "backend/vulkan/ShaderModuleVk.h" #include "backend/vulkan/SwapChainVk.h" #include "backend/vulkan/TextureVk.h" diff --git a/src/backend/vulkan/SamplerVk.cpp b/src/backend/vulkan/SamplerVk.cpp new file mode 100644 index 0000000000..d94632518f --- /dev/null +++ b/src/backend/vulkan/SamplerVk.cpp @@ -0,0 +1,98 @@ +// Copyright 2018 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "backend/vulkan/SamplerVk.h" + +#include "backend/vulkan/FencedDeleter.h" +#include "backend/vulkan/VulkanBackend.h" + +namespace backend { namespace vulkan { + + namespace { + VkSamplerAddressMode VulkanSamplerAddressMode(nxt::AddressMode mode) { + switch (mode) { + case nxt::AddressMode::Repeat: + return VK_SAMPLER_ADDRESS_MODE_REPEAT; + case nxt::AddressMode::MirroredRepeat: + return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; + case nxt::AddressMode::ClampToEdge: + return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + default: + UNREACHABLE(); + } + } + + VkFilter VulkanSamplerFilter(nxt::FilterMode filter) { + switch (filter) { + case nxt::FilterMode::Linear: + return VK_FILTER_LINEAR; + case nxt::FilterMode::Nearest: + return VK_FILTER_NEAREST; + default: + UNREACHABLE(); + } + } + + VkSamplerMipmapMode VulkanMipMapMode(nxt::FilterMode filter) { + switch (filter) { + case nxt::FilterMode::Linear: + return VK_SAMPLER_MIPMAP_MODE_LINEAR; + case nxt::FilterMode::Nearest: + return VK_SAMPLER_MIPMAP_MODE_NEAREST; + default: + UNREACHABLE(); + } + } + } // anonymous namespace + + Sampler::Sampler(SamplerBuilder* builder) + : SamplerBase(builder), mDevice(ToBackend(builder->GetDevice())) { + VkSamplerCreateInfo createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.magFilter = VulkanSamplerFilter(builder->GetMagFilter()); + createInfo.minFilter = VulkanSamplerFilter(builder->GetMinFilter()); + createInfo.mipmapMode = VulkanMipMapMode(builder->GetMipMapFilter()); + createInfo.addressModeU = VulkanSamplerAddressMode(builder->GetAddressModeU()); + createInfo.addressModeV = VulkanSamplerAddressMode(builder->GetAddressModeV()); + createInfo.addressModeW = VulkanSamplerAddressMode(builder->GetAddressModeW()); + createInfo.mipLodBias = 0.0f; + createInfo.anisotropyEnable = VK_FALSE; + createInfo.maxAnisotropy = 1.0f; + createInfo.compareEnable = VK_FALSE; + createInfo.compareOp = VK_COMPARE_OP_NEVER; + createInfo.minLod = 0.0f; + createInfo.maxLod = 1000.0f; + createInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; + createInfo.unnormalizedCoordinates = VK_FALSE; + + if (mDevice->fn.CreateSampler(mDevice->GetVkDevice(), &createInfo, nullptr, &mHandle) != + VK_SUCCESS) { + ASSERT(false); + } + } + + Sampler::~Sampler() { + if (mHandle != VK_NULL_HANDLE) { + mDevice->GetFencedDeleter()->DeleteWhenUnused(mHandle); + mHandle = VK_NULL_HANDLE; + } + } + + VkSampler Sampler::GetHandle() const { + return mHandle; + } + +}} // namespace backend::vulkan diff --git a/src/backend/vulkan/SamplerVk.h b/src/backend/vulkan/SamplerVk.h new file mode 100644 index 0000000000..c5b4c2234e --- /dev/null +++ b/src/backend/vulkan/SamplerVk.h @@ -0,0 +1,39 @@ +// Copyright 2018 The NXT Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BACKEND_VULKAN_SAMPLERVK_H_ +#define BACKEND_VULKAN_SAMPLERVK_H_ + +#include "backend/Sampler.h" + +#include "backend/vulkan/MemoryAllocator.h" +#include "common/vulkan_platform.h" + +namespace backend { namespace vulkan { + + class Sampler : public SamplerBase { + public: + Sampler(SamplerBuilder* builder); + ~Sampler(); + + VkSampler GetHandle() const; + + private: + VkSampler mHandle = VK_NULL_HANDLE; + Device* mDevice = nullptr; + }; + +}} // namespace backend::vulkan + +#endif // BACKEND_VULKAN_SAMPLERVK_H_ diff --git a/src/backend/vulkan/VulkanBackend.cpp b/src/backend/vulkan/VulkanBackend.cpp index 9396de411b..732f3a4031 100644 --- a/src/backend/vulkan/VulkanBackend.cpp +++ b/src/backend/vulkan/VulkanBackend.cpp @@ -29,6 +29,7 @@ #include "backend/vulkan/PipelineLayoutVk.h" #include "backend/vulkan/RenderPassVk.h" #include "backend/vulkan/RenderPipelineVk.h" +#include "backend/vulkan/SamplerVk.h" #include "backend/vulkan/ShaderModuleVk.h" #include "backend/vulkan/SwapChainVk.h" #include "backend/vulkan/TextureVk.h" diff --git a/src/backend/vulkan/VulkanBackend.h b/src/backend/vulkan/VulkanBackend.h index 002cf1c24e..41c79a11c6 100644 --- a/src/backend/vulkan/VulkanBackend.h +++ b/src/backend/vulkan/VulkanBackend.h @@ -47,7 +47,7 @@ namespace backend { namespace vulkan { class Queue; class RenderPass; class RenderPipeline; - using Sampler = SamplerBase; + class Sampler; class ShaderModule; class SwapChain; class Texture;