1 /* Copyright (C) 2022 Wildfire Games.
2 * This file is part of 0 A.D.
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.
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.
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/>.
18 #include "precompiled.h"
20 #include "ShaderDefines.h"
22 #include "graphics/ShaderProgram.h"
24 #include "maths/Vector4D.h"
25 #include "ps/ThreadUtil.h"
33 struct hash
<CVector4D
>
35 std::size_t operator()(const CVector4D
& v
) const
38 hash_combine(hash
, v
.X
);
39 hash_combine(hash
, v
.Y
);
40 hash_combine(hash
, v
.Z
);
41 hash_combine(hash
, v
.W
);
47 bool operator==(const CShaderParams
<CStrIntern
>::SItems
& a
, const CShaderParams
<CStrIntern
>::SItems
& b
)
49 return a
.items
== b
.items
;
52 bool operator==(const CShaderParams
<CVector4D
>::SItems
& a
, const CShaderParams
<CVector4D
>::SItems
& b
)
54 return a
.items
== b
.items
;
57 template<typename value_t
>
58 bool CShaderParams
<value_t
>::SItems::NameLess(const Item
& a
, const Item
& b
)
60 return a
.first
< b
.first
;
63 template<typename value_t
>
64 typename CShaderParams
<value_t
>::SItems
* CShaderParams
<value_t
>::GetInterned(const SItems
& items
)
66 ENSURE(Threading::IsMainThread()); // s_InternedItems is not thread-safe
68 typename
InternedItems_t::iterator it
= s_InternedItems
.find(items
);
69 if (it
!= s_InternedItems
.end())
70 return it
->second
.get();
72 // Sanity test: the items list is meant to be sorted by name.
73 // This is a reasonable place to verify that, since this will be called once per distinct SItems.
74 ENSURE(std::is_sorted(items
.items
.begin(), items
.items
.end(), SItems::NameLess
));
76 std::shared_ptr
<SItems
> ptr
= std::make_shared
<SItems
>(items
);
77 s_InternedItems
.insert(std::make_pair(items
, ptr
));
81 template<typename value_t
>
82 CShaderParams
<value_t
>::CShaderParams()
87 template<typename value_t
>
88 CShaderParams
<value_t
>::CShaderParams(SItems
* items
) : m_Items(items
)
92 template<typename value_t
>
93 CShaderParams
<value_t
> CShaderParams
<value_t
>::CreateEmpty()
97 return CShaderParams(GetInterned(items
));
100 template<typename value_t
>
101 void CShaderParams
<value_t
>::Set(CStrIntern name
, const value_t
& value
)
103 SItems items
= *m_Items
;
105 typename
SItems::Item addedItem
= std::make_pair(name
, value
);
107 // Add the new item in a way that preserves the sortedness and uniqueness of item names
108 for (typename
std::vector
<typename
SItems::Item
>::iterator it
= items
.items
.begin(); ; ++it
)
110 if (it
== items
.items
.end() || addedItem
.first
< it
->first
)
112 items
.items
.insert(it
, addedItem
);
115 else if (addedItem
.first
== it
->first
)
117 it
->second
= addedItem
.second
;
123 m_Items
= GetInterned(items
);
126 template<typename value_t
>
127 void CShaderParams
<value_t
>::SetMany(const CShaderParams
& params
)
130 // set_union merges the two sorted lists into a new sorted list;
131 // if two items are equivalent (i.e. equal names, possibly different values)
132 // then the one from the first list is kept
134 params
.m_Items
->items
.begin(), params
.m_Items
->items
.end(),
135 m_Items
->items
.begin(), m_Items
->items
.end(),
136 std::inserter(items
.items
, items
.items
.begin()),
139 m_Items
= GetInterned(items
);
142 template<typename value_t
>
143 std::map
<CStrIntern
, value_t
> CShaderParams
<value_t
>::GetMap() const
145 std::map
<CStrIntern
, value_t
> ret
;
146 for (size_t i
= 0; i
< m_Items
->items
.size(); ++i
)
147 ret
[m_Items
->items
[i
].first
] = m_Items
->items
[i
].second
;
151 template<typename value_t
>
152 size_t CShaderParams
<value_t
>::GetHash() const
154 return m_Items
->hash
;
157 template<typename value_t
>
158 void CShaderParams
<value_t
>::SItems::RecalcHash()
161 for (size_t i
= 0; i
< items
.size(); ++i
)
163 hash_combine(h
, items
[i
].first
);
164 hash_combine(h
, items
[i
].second
);
170 void CShaderDefines::Add(CStrIntern name
, CStrIntern value
)
175 int CShaderDefines::GetInt(const char* name
) const
177 CStrIntern
nameIntern(name
);
178 for (size_t i
= 0; i
< m_Items
->items
.size(); ++i
)
180 if (m_Items
->items
[i
].first
== nameIntern
)
183 std::stringstream
str(m_Items
->items
[i
].second
.c_str());
192 void CShaderUniforms::Add(const char* name
, const CVector4D
& value
)
194 Set(CStrIntern(name
), value
);
197 CVector4D
CShaderUniforms::GetVector(const char* name
) const
199 CStrIntern
nameIntern(name
);
200 for (size_t i
= 0; i
< m_Items
->items
.size(); ++i
)
202 if (m_Items
->items
[i
].first
== nameIntern
)
204 return m_Items
->items
[i
].second
;
210 void CShaderUniforms::BindUniforms(
211 Renderer::Backend::IDeviceCommandContext
* deviceCommandContext
,
212 Renderer::Backend::IShaderProgram
* shader
) const
214 for (const SItems::Item
& item
: m_Items
->items
)
216 const CVector4D
& v
= item
.second
;
217 deviceCommandContext
->SetUniform(
218 shader
->GetBindingSlot(item
.first
), v
.AsFloatArray());
222 void CShaderRenderQueries::Add(const char* name
)
224 if (name
== CStr("sim_time"))
226 m_Items
.emplace_back(RQUERY_TIME
, CStrIntern(name
));
228 else if (name
== CStr("water_tex"))
230 m_Items
.emplace_back(RQUERY_WATER_TEX
, CStrIntern(name
));
232 else if (name
== CStr("sky_cube"))
234 m_Items
.emplace_back(RQUERY_SKY_CUBE
, CStrIntern(name
));
238 // Explicit instantiations:
240 template<> CShaderParams
<CStrIntern
>::InternedItems_t CShaderParams
<CStrIntern
>::s_InternedItems
= CShaderParams
<CStrIntern
>::InternedItems_t();
241 template<> CShaderParams
<CVector4D
>::InternedItems_t CShaderParams
<CVector4D
>::s_InternedItems
= CShaderParams
<CVector4D
>::InternedItems_t();
243 template<> CShaderParams
<CStrIntern
> CShaderParams
<CStrIntern
>::s_Empty
= CShaderParams
<CStrIntern
>::CreateEmpty();
244 template<> CShaderParams
<CVector4D
> CShaderParams
<CVector4D
>::s_Empty
= CShaderParams
<CVector4D
>::CreateEmpty();
246 template class CShaderParams
<CStrIntern
>;
247 template class CShaderParams
<CVector4D
>;