Line data Source code
1 : /* Copyright (C) 2023 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "SamplerManager.h"
21 :
22 : #include "lib/hash.h"
23 : #include "renderer/backend/vulkan/Device.h"
24 : #include "renderer/backend/vulkan/Mapping.h"
25 : #include "renderer/backend/vulkan/Utilities.h"
26 :
27 : namespace Renderer
28 : {
29 :
30 : namespace Backend
31 : {
32 :
33 : namespace Vulkan
34 : {
35 :
36 0 : size_t CSamplerManager::SamplerDescHash::operator()(const Sampler::Desc& samplerDesc) const
37 : {
38 0 : size_t seed = 0;
39 :
40 0 : hash_combine(seed, samplerDesc.magFilter);
41 0 : hash_combine(seed, samplerDesc.minFilter);
42 0 : hash_combine(seed, samplerDesc.mipFilter);
43 0 : hash_combine(seed, samplerDesc.addressModeU);
44 0 : hash_combine(seed, samplerDesc.addressModeV);
45 0 : hash_combine(seed, samplerDesc.addressModeW);
46 :
47 0 : hash_combine(seed, samplerDesc.mipLODBias);
48 0 : hash_combine(seed, samplerDesc.anisotropyEnabled);
49 0 : hash_combine(seed, samplerDesc.maxAnisotropy);
50 :
51 0 : hash_combine(seed, samplerDesc.borderColor);
52 0 : hash_combine(seed, samplerDesc.compareEnabled);
53 0 : hash_combine(seed, samplerDesc.compareOp);
54 :
55 0 : return seed;
56 : }
57 :
58 0 : bool CSamplerManager::SamplerDescEqual::operator()(const Sampler::Desc& lhs, const Sampler::Desc& rhs) const
59 : {
60 : return
61 0 : lhs.magFilter == rhs.magFilter &&
62 0 : lhs.minFilter == rhs.minFilter &&
63 0 : lhs.mipFilter == rhs.mipFilter &&
64 0 : lhs.addressModeU == rhs.addressModeU &&
65 0 : lhs.addressModeV == rhs.addressModeV &&
66 0 : lhs.addressModeW == rhs.addressModeW &&
67 0 : lhs.mipLODBias == rhs.mipLODBias &&
68 0 : lhs.anisotropyEnabled == rhs.anisotropyEnabled &&
69 0 : lhs.maxAnisotropy == rhs.maxAnisotropy &&
70 0 : lhs.borderColor == rhs.borderColor &&
71 0 : lhs.compareEnabled == rhs.compareEnabled &&
72 0 : lhs.compareOp == rhs.compareOp;
73 : }
74 :
75 0 : CSamplerManager::CSamplerManager(CDevice* device)
76 0 : : m_Device(device)
77 : {
78 0 : }
79 :
80 0 : CSamplerManager::~CSamplerManager()
81 : {
82 0 : for (const auto& it : m_SamplerMap)
83 0 : if (it.second != VK_NULL_HANDLE)
84 : {
85 0 : m_Device->ScheduleObjectToDestroy(
86 0 : VK_OBJECT_TYPE_SAMPLER, it.second, VK_NULL_HANDLE);
87 : }
88 0 : m_SamplerMap.clear();
89 0 : }
90 :
91 0 : VkSampler CSamplerManager::GetOrCreateSampler(
92 : const Sampler::Desc& samplerDesc)
93 : {
94 0 : auto it = m_SamplerMap.find(samplerDesc);
95 0 : if (it != m_SamplerMap.end())
96 0 : return it->second;
97 :
98 0 : VkSamplerCreateInfo samplerCreateInfo{};
99 0 : samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
100 0 : samplerCreateInfo.magFilter = samplerDesc.magFilter == Sampler::Filter::LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
101 0 : samplerCreateInfo.minFilter = samplerDesc.minFilter == Sampler::Filter::LINEAR ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
102 0 : samplerCreateInfo.mipmapMode = samplerDesc.mipFilter == Sampler::Filter::LINEAR ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST;
103 0 : samplerCreateInfo.addressModeU = Mapping::FromAddressMode(samplerDesc.addressModeU);
104 0 : samplerCreateInfo.addressModeV = Mapping::FromAddressMode(samplerDesc.addressModeV);
105 0 : samplerCreateInfo.addressModeW = Mapping::FromAddressMode(samplerDesc.addressModeW);
106 0 : if (samplerDesc.anisotropyEnabled && m_Device->GetCapabilities().anisotropicFiltering)
107 : {
108 0 : samplerCreateInfo.anisotropyEnable = VK_TRUE;
109 0 : samplerCreateInfo.maxAnisotropy = samplerDesc.maxAnisotropy;
110 : }
111 0 : samplerCreateInfo.compareEnable = samplerDesc.compareEnabled ? VK_TRUE : VK_FALSE;
112 0 : samplerCreateInfo.compareOp = Mapping::FromCompareOp(samplerDesc.compareOp);
113 0 : samplerCreateInfo.minLod = -1000.0f;
114 0 : samplerCreateInfo.maxLod = 1000.0f;
115 0 : switch (samplerDesc.borderColor)
116 : {
117 0 : case Sampler::BorderColor::TRANSPARENT_BLACK:
118 0 : samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
119 0 : break;
120 0 : case Sampler::BorderColor::OPAQUE_BLACK:
121 0 : samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
122 0 : break;
123 0 : case Sampler::BorderColor::OPAQUE_WHITE:
124 0 : samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
125 0 : break;
126 : }
127 :
128 0 : VkSampler sampler = VK_NULL_HANDLE;
129 0 : ENSURE_VK_SUCCESS(vkCreateSampler(
130 : m_Device->GetVkDevice(), &samplerCreateInfo, nullptr, &sampler));
131 0 : it = m_SamplerMap.emplace(samplerDesc, sampler).first;
132 :
133 0 : return sampler;
134 : }
135 :
136 : } // namespace Vulkan
137 :
138 : } // namespace Backend
139 :
140 3 : } // namespace Renderer
|