vkmEngine 1.0.0
A C++ game engine · vkmengine.com
Loading...
Searching...
No Matches
texture_format.h
1#pragma once
2
3#include <algorithm>
4#include <cstdint>
5
6#include "core/reflect.h"
7
8namespace Vkm::Engine {
9
10// Every enum TextureParams holds is persisted by value in cooked textures: append only. A reorder
11// silently re-reads cooked textures as another format; writeTexture in io/asset/asset_cook.cpp pins
12// every enumerator.
13
19enum class TextureInternalFormat : uint8_t {
20 R8,
21 RG8,
22 RGB8,
23 RGBA8,
24 SRGB8,
25 SRGBA8,
26 RGBA16F,
27 RGBA32F,
28 BC4R,
29 BC5RG,
30 BC7RGBA,
31 BC7SRGBA
32};
33
37enum class TexturePixelFormat : uint8_t {
38 R,
39 RG,
40 RGB,
41 RGBA
42};
43
47enum class TexturePixelType : uint8_t {
48 UnsignedByte,
49 Float,
50 HalfFloat
51};
52
56enum class TextureWrapMode : uint8_t {
57 Repeat,
58 MirroredRepeat,
59 ClampToEdge,
60 ClampToBorder
61};
62
69enum class TextureFilterOverride : uint8_t {
70 None,
71 Nearest
72};
73
78 uint32_t width = 0;
79 uint32_t height = 0;
80
81 TextureInternalFormat internalFormat = TextureInternalFormat::RGBA8;
82 TexturePixelFormat format = TexturePixelFormat::RGBA;
83 TexturePixelType type = TexturePixelType::UnsignedByte;
84
85 TextureWrapMode wrapS = TextureWrapMode::ClampToEdge;
86 TextureWrapMode wrapT = TextureWrapMode::ClampToEdge;
87
88 TextureFilterOverride filterOverride = TextureFilterOverride::None;
89
90 bool generateMipmaps = true;
91
93 uint32_t mipLevels = 1;
94};
95
103enum class TextureUsage : uint8_t {
104 Color,
105 Data,
106 Normal,
107 Count
108};
109
121inline int decodeChannels(int fileChannels, TextureUsage usage) {
122 if (usage == TextureUsage::Normal) return 2;
123 if (fileChannels == 2 || (fileChannels == 1 && usage == TextureUsage::Color)) return 4;
124 return fileChannels;
125}
126
137inline TextureInternalFormat inferInternalFormat(int channels, TextureUsage usage) {
138 if (usage == TextureUsage::Color) {
139 return (channels == 3) ? TextureInternalFormat::SRGB8 : TextureInternalFormat::SRGBA8;
140 }
141 if (usage == TextureUsage::Normal) return TextureInternalFormat::RG8;
142 switch (channels) {
143 case 1: return TextureInternalFormat::R8;
144 case 3: return TextureInternalFormat::RGB8;
145 default: return TextureInternalFormat::RGBA8;
146 }
147}
148
155inline bool isSrgbFormat(TextureInternalFormat format) {
156 return format == TextureInternalFormat::SRGB8 || format == TextureInternalFormat::SRGBA8
157 || format == TextureInternalFormat::BC7SRGBA;
158}
159
166inline TextureUsage textureUsageOf(TextureInternalFormat format) {
167 if (isSrgbFormat(format)) return TextureUsage::Color;
168 if (format == TextureInternalFormat::RG8 || format == TextureInternalFormat::BC5RG) {
169 return TextureUsage::Normal;
170 }
171 return TextureUsage::Data;
172}
173
180inline uint64_t blockBytes(TextureInternalFormat format) {
181 switch (format) {
182 case TextureInternalFormat::BC4R: return 8;
183 case TextureInternalFormat::BC5RG:
184 case TextureInternalFormat::BC7RGBA:
185 case TextureInternalFormat::BC7SRGBA: return 16;
186 case TextureInternalFormat::R8:
187 case TextureInternalFormat::RG8:
188 case TextureInternalFormat::RGB8:
189 case TextureInternalFormat::RGBA8:
190 case TextureInternalFormat::SRGB8:
191 case TextureInternalFormat::SRGBA8:
192 case TextureInternalFormat::RGBA16F:
193 case TextureInternalFormat::RGBA32F: return 0;
194 }
195 return 0;
196}
197
204inline bool isCompressedFormat(TextureInternalFormat format) {
205 return blockBytes(format) != 0;
206}
207
216inline uint32_t channelCount(TexturePixelFormat format) {
217 switch (format) {
218 case TexturePixelFormat::R: return 1;
219 case TexturePixelFormat::RG: return 2;
220 case TexturePixelFormat::RGB: return 3;
221 case TexturePixelFormat::RGBA: return 4;
222 }
223 return 4;
224}
225
235inline uint64_t bytesPerTexel(TexturePixelFormat format, TexturePixelType type) {
236 const uint64_t channels = channelCount(format);
237 uint64_t componentBytes = 1;
238 switch (type) {
239 case TexturePixelType::UnsignedByte: componentBytes = 1; break;
240 case TexturePixelType::HalfFloat: componentBytes = 2; break;
241 case TexturePixelType::Float: componentBytes = 4; break;
242 }
243 return channels * componentBytes;
244}
245
253inline uint32_t mipChainLength(uint32_t width, uint32_t height) {
254 if (width == 0 || height == 0) return 0;
255 uint32_t extent = std::max(width, height);
256 uint32_t levels = 1;
257 while (extent > 1) {
258 extent >>= 1;
259 ++levels;
260 }
261 return levels;
262}
263
271inline uint32_t mipExtent(uint32_t extent, uint32_t level) {
272 return (level >= 32) ? 1u : std::max(extent >> level, 1u);
273}
274
281inline uint64_t textureUnitBytes(const TextureParams& params) {
282 return isCompressedFormat(params.internalFormat)
283 ? blockBytes(params.internalFormat)
284 : bytesPerTexel(params.format, params.type);
285}
286
296inline uint64_t textureLevelUnits(const TextureParams& params, uint32_t level) {
297 const uint64_t width = mipExtent(params.width, level);
298 const uint64_t height = mipExtent(params.height, level);
299 if (!isCompressedFormat(params.internalFormat)) return width * height;
300 return ((width + 3) / 4) * ((height + 3) / 4);
301}
302
313inline uint64_t textureLevelBytes(const TextureParams& params, uint32_t level) {
314 return textureLevelUnits(params, level) * textureUnitBytes(params);
315}
316
325inline bool buildsMipsAtUpload(const TextureParams& params) {
326 return params.generateMipmaps && params.mipLevels == 1 && !isCompressedFormat(params.internalFormat);
327}
328
337inline bool isMipmapped(const TextureParams& params) {
338 return params.mipLevels > 1 || buildsMipsAtUpload(params);
339}
340
347inline TexturePixelFormat inferFormat(int channels) {
348 switch (channels) {
349 case 1: return TexturePixelFormat::R;
350 case 2: return TexturePixelFormat::RG;
351 case 3: return TexturePixelFormat::RGB;
352 case 4:
353 default: return TexturePixelFormat::RGBA;
354 }
355}
356
357} // namespace Vkm::Engine
358
359VKM_ENUM_NAMES(::Vkm::Engine::TextureUsage, "Color", "Data", "Normal")
Full sampling + storage description for a texture, consumed by the backend on upload.
Definition texture_format.h:77
uint32_t mipLevels
Levels the pixel data carries, level 0 first: one, or the whole chain down to 1x1.
Definition texture_format.h:93