Cogs.Core
TexturesGLES30.cpp
1#include "TexturesGLES30.h"
2
3#include <algorithm>
4
5#include "FormatsGLES30.h"
6#include "CapabilitiesGLES30.h"
7#include "ContextGLES30.h"
8
9#include "Foundation/Logging/Logger.h"
10
11using namespace Cogs;
12
13namespace
14{
15 Cogs::Logging::Log logger = Cogs::Logging::getLogger("TexturesGLES30");
16
17
18 Cogs::TextureHandle logAndReturnInvalidHandle(const Cogs::TextureDescription& desc)
19 {
20 LOG_ERROR(logger, "Illegal %s description (width=%u, height=%u, depth=%u, layers=%u, faces=%u, levels=%u, samples=%u)",
21 getResourceDimensionsName(desc.target), desc.width, desc.height, desc.depth, desc.layers, desc.faces, desc.levels, desc.samples);
23 }
24
25 // Clamp the sample count to max supported for a particular format
26 uint32_t clampFormatSampleCount(Cogs::TextureFormat format, uint8_t numSamples)
27 {
28 const OpenGLES30::DataFormatInfo& fmt = OpenGLES30::DataFormats[size_t(format)];
29
30 // Clamp sample count
31 GLint maxSampleCount = 0;
32 glGetInternalformativ(GL_RENDERBUFFER, fmt.internalFormat, GL_SAMPLES, 1, &maxSampleCount);
33 assert(0 <= maxSampleCount);
34
35 if (uint32_t(maxSampleCount) < numSamples) {
36 LOG_DEBUG(logger, "Requested sample count %u greater than maximum %d for format %s, clamping.",
37 numSamples, maxSampleCount, getFormatInfo(format)->name);
38 return maxSampleCount;
39 }
40 return numSamples;
41 }
42
43}
44
46{
47 const bool generateMips = (desc.flags & TextureFlags::GenerateMipMaps) != 0;
48
49 TextureGLES30 texture{ };
50 texture.width = desc.width;
51 texture.height = desc.height;
52 texture.depth = 1;
53 texture.estimatedByteSize = uint32_t(desc.estimateMemorySize());
54 texture.flags = desc.flags;
55 texture.numSamples = uint8_t(desc.samples);
56 texture.textureId = 0;
57 texture.renderBuffer = 0;
58 texture.fbo = 0;
59 texture.format = desc.format;
60 texture.cubeMap = false;
61 texture.hasMipmaps = generateMips || desc.levels > 1;
62
63 // Sanity checks
64 const OpenGLES30::DataFormatInfo& fmt = OpenGLES30::DataFormats[size_t(texture.format)];
65 if (fmt.isTextureFormat == 0) {
67 }
68 if (data && fmt.isCompressed) {
69 texture.estimatedByteSize = uint32_t(data->getSize());
70 }
71
72 switch (desc.target) {
73 case ResourceDimensions::Unknown:
74 case ResourceDimensions::Buffer:
75 case ResourceDimensions::Texture1D:
76 case ResourceDimensions::Texture1DArray:
77 case ResourceDimensions::Texture3DArray:
78 case ResourceDimensions::TextureCubeArray:
79 case ResourceDimensions::Texture2DMSArray:
80 LOG_ERROR(logger, "Unsupported texture resource dimension %s", getResourceDimensionsName(desc.target));
82
83 case ResourceDimensions::Texture2DMS:
84 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers != 1 || desc.faces != 1 || desc.samples == 0) {
85 return logAndReturnInvalidHandle(desc);
86 }
87 else {
88 texture.target = GL_TEXTURE_2D_MULTISAMPLE; // Not directly supported, used to specify that data is in a renderbuffer
89
90 texture.numSamples = static_cast<uint8_t>(clampFormatSampleCount(texture.format, texture.numSamples));
91
92 // Set up renderbuffer
93 glGenRenderbuffers(1, &texture.renderBuffer);
94 glBindRenderbuffer(GL_RENDERBUFFER, texture.renderBuffer);
95 glRenderbufferStorageMultisample(GL_RENDERBUFFER, texture.numSamples, fmt.internalFormat, texture.width, texture.height);
96 glBindRenderbuffer(GL_RENDERBUFFER, 0);
97
98 // Set up framebuffer
99 GLenum framebufferAttachment = (texture.flags & Cogs::TextureFlags::DepthBuffer) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0;
100 glGenFramebuffers(1, &texture.fbo);
101 glBindFramebuffer(GL_READ_FRAMEBUFFER, texture.fbo);
102 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, framebufferAttachment, GL_RENDERBUFFER, texture.renderBuffer);
103 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
104
105 GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
106 if (status != GL_FRAMEBUFFER_COMPLETE) {
107 LOG_ERROR(logger, "Failed to create multisample texture rendertarget: %s", OpenGLES30::framebuffersStatusString(status));
108 glDeleteFramebuffers(1, &texture.fbo);
109 glDeleteRenderbuffers(1, &texture.renderBuffer);
111 }
112
113 return textures.addResource(texture);
114 }
115 break;
116
117 case ResourceDimensions::Texture2D:
118 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers != 1 || desc.faces != 1 || desc.samples != 1) {
119 return logAndReturnInvalidHandle(desc);
120 }
121 texture.target = GL_TEXTURE_2D;
122 break;
123 case ResourceDimensions::Texture2DArray:
124 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers == 0 || desc.faces != 1 || desc.samples != 1) {
125 return logAndReturnInvalidHandle(desc);
126 }
127 texture.target = GL_TEXTURE_2D_ARRAY;
128 texture.depth = desc.layers;
129 break;
130 case ResourceDimensions::Texture3D:
131 if (desc.width == 0 || desc.height == 0 || desc.depth == 0 || desc.layers != 1 || desc.faces != 1 || desc.samples != 1) {
132 return logAndReturnInvalidHandle(desc);
133 }
134 texture.target = GL_TEXTURE_3D;
135 texture.depth = desc.depth;
136 break;
137 case ResourceDimensions::TextureCube:
138 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers != 1 || desc.faces != 6 || desc.samples != 1) {
139 return logAndReturnInvalidHandle(desc);
140 }
141 texture.target = GL_TEXTURE_CUBE_MAP;
142 texture.depth = desc.depth;
143 texture.cubeMap = true;
144 break;
145
146 case ResourceDimensions::RenderBuffer:
147 if (desc.width == 0 || desc.height == 0 || desc.depth != 1 || desc.layers != 1 || desc.faces != 1 || desc.levels != 1) {
148 return logAndReturnInvalidHandle(desc);
149 }
150 if (generateMips) {
151 LOG_ERROR(logger, "RenderBuffers do not support mipmaps");
153 }
154 texture.target = GL_RENDERBUFFER;
155 texture.numSamples = static_cast<uint8_t>(clampFormatSampleCount(texture.format, texture.numSamples));
156 break;
157 default:
158 assert(false && "Invalid enum");
159 break;
160 }
161
162 GLuint textureLevels;
163 if (generateMips) {
164 textureLevels = 1 + static_cast<GLuint>(std::floor(std::log((double)std::max(desc.width, desc.height)) / std::log(2.0)));
165 }
166 else {
167 textureLevels = static_cast<GLuint>(desc.levels);
168 }
169
170
172
173 // If texture is a render buffer
174 if (texture.target == GL_RENDERBUFFER) {
175
176 texture.textureId = 0;
177 if (texture.flags & TextureFlags::ExternalTexture) {
178 assert(data != nullptr);
179 texture.renderBuffer = static_cast<GLuint>(data->externalHandle);
180 }
181 else {
182 glGenRenderbuffers(1, &texture.renderBuffer);
183 glBindRenderbuffer(GL_RENDERBUFFER, texture.renderBuffer);
184 glRenderbufferStorageMultisample(GL_RENDERBUFFER, texture.numSamples, fmt.internalFormat, texture.width, texture.height);
185 glBindRenderbuffer(GL_RENDERBUFFER, 0);
186 }
187 textureHandle = textures.addResource(texture);
188 }
189
190 // If texture is an actual texture
191 else {
192 if (desc.flags & TextureFlags::ExternalTexture) {
193 assert(data != nullptr);
194 texture.textureId = static_cast<GLuint>(data->externalHandle);
195 textureHandle = textures.addResource(texture);
196
197 if (generateMips) {
198 if (TextureGLES30* tex = context->bindTexture(textureHandle); tex) {
199 glGenerateMipmap(tex->target);
200 }
201 }
202 }
203 else {
204 glGenTextures(1, &texture.textureId);
205 textureHandle = textures.addResource(texture);
206
207 if (TextureGLES30* tex = context->bindTexture(textureHandle); tex) {
208 defineTextureData(tex, textureLevels);
209 if (data) {
210 uploadTextureData(*tex, *data, 0, 0, 0);
211 }
212 else if (generateMips) {
213 glGenerateMipmap(tex->target);
214 }
215 }
216 }
217 }
218
219 textureMemoryConsumption += texture.estimatedByteSize;
220 return textureHandle;
221}
222
223void Cogs::TexturesGLES30::uploadTextureData(TextureGLES30& tex,
224 const TextureData& data,
225 uint32_t layer_offset,
226 uint32_t face_offset,
227 uint32_t level_offset)
228{
229 assert(face_offset == 0 && "face_offset not handled");
230 assert(level_offset == 0 && "level_offset not handled");
231
232 const OpenGLES30::DataFormatInfo& fmt = OpenGLES30::DataFormats[size_t(tex.format)];
233 const bool isCompressed = fmt.isCompressed;
234 const GLenum target = tex.target;
235 const GLenum textureFormat = fmt.internalFormat;
236 const GLenum pixelType = fmt.type;
237 const GLenum pixelFormat = fmt.format;
238
239 if(context->uploadStatisticsEnabled) context->uploadStatisticsTextureUpload(data.getSize());
240
241 if (isCompressed) {
242 switch (target) {
243 case GL_TEXTURE_2D:
244 for (size_t j = 0; j < data.levels; ++j) {
245 TextureExtent ext = data.getExtent(j);
246 glCompressedTexSubImage2D(target, static_cast<GLint>(j), 0, 0, ext.width, ext.height, textureFormat, static_cast<GLsizei>(data.getLevelSize(j)), data.getData(0, 0, j));
247 }
248 break;
249 case GL_TEXTURE_CUBE_MAP:
250 for (size_t j = 0; j < data.levels; ++j) {
251 for (GLint c = 0; c < 6; ++c) {
252 TextureExtent ext = data.getExtent(j);
253 glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + c, static_cast<GLint>(j), 0, 0, ext.width, ext.height, textureFormat, GLsizei(data.getLevelSize(j)), data.getData(0, c, j));
254 }
255 }
256 break;
257 case GL_TEXTURE_2D_ARRAY: [[fallthrough]];
258 case GL_TEXTURE_2D_MULTISAMPLE: [[fallthrough]];
259 case GL_TEXTURE_3D: [[fallthrough]];
260 case GL_INVALID_ENUM:
261 LOG_ERROR(logger, "Texture target #%04x cannot use compressed formats", target);
262 break;
263 }
264 }
265 else {
266 switch (target) {
267 case GL_TEXTURE_2D:
268 for (size_t j = 0; j < data.levels; ++j) {
269 TextureExtent ext = data.getExtent(j);
270 glTexSubImage2D(target, static_cast<GLint>(j), 0, 0, ext.width, ext.height, pixelFormat, pixelType, data.getData(0, 0, j));
271 }
272 break;
273 case GL_TEXTURE_2D_ARRAY:
274 for (size_t i = 0; i < data.layers; ++i) {
275 for (size_t j = 0; j < data.levels; ++j) {
276 TextureExtent ext = data.getExtent(j);
277 glTexSubImage3D(target, static_cast<GLint>(j),
278 0, 0, static_cast<GLint>(layer_offset + i), ext.width, ext.height, 1,
279 pixelFormat, pixelType, data.getData(i, 0, j));
280 }
281 }
282 break;
283 case GL_TEXTURE_3D:
284 for (size_t j = 0; j < data.levels; ++j) {
285 TextureExtent ext = data.getExtent(j);
286 glTexSubImage3D(target, static_cast<GLint>(j),
287 0, 0, 0, ext.width, ext.height, ext.depth,
288 pixelFormat, pixelType, data.getData(0, 0, j));
289 }
290 break;
291 case GL_TEXTURE_CUBE_MAP:
292 for (size_t j = 0; j < data.levels; ++j) {
293 for (GLint c = 0; c < 6; ++c) {
294 TextureExtent ext = data.getExtent(j);
295 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + c, (GLint)j,
296 0, 0, ext.width, ext.height,
297 pixelFormat, pixelType, data.getData(0, c, j));
298 }
299 }
300 break;
301 case GL_TEXTURE_2D_MULTISAMPLE: [[fallthrough]];
302 case GL_INVALID_ENUM:
303 LOG_ERROR(logger, "Texture target #%04x cannot get data uploaded", target);
304 break;
305 }
306 }
307
308 const bool generateMips = (tex.flags & TextureFlags::GenerateMipMaps) != 0;
309 if (generateMips) {
310 glGenerateMipmap(target);
311 }
312}
313
314void Cogs::TexturesGLES30::uploadTextureData(TextureHandle textureHandle,
315 const TextureData& data,
316 uint32_t layer_offset,
317 uint32_t face_offset,
318 uint32_t level_offset)
319{
320 TextureGLES30& texture = this->textures[textureHandle];
321 const GLenum target = texture.target;
322 glBindTexture(target, texture.textureId);
323 uploadTextureData(texture, data, layer_offset, face_offset, level_offset);
324 glBindTexture(target, 0);
325}
326
327
328void Cogs::TexturesGLES30::defineTextureData(TextureGLES30* tex, GLuint textureLevels)
329{
330 const OpenGLES30::DataFormatInfo& fmt = OpenGLES30::DataFormats[size_t(tex->format)];
331 assert(fmt.isTextureFormat);
332
333 switch (tex->target) {
334
335 case GL_TEXTURE_2D:
336 glTexStorage2D(GL_TEXTURE_2D, textureLevels, fmt.internalFormat, tex->width, tex->height);
337 break;
338
339 case GL_TEXTURE_CUBE_MAP:
340 glTexStorage2D(tex->target, textureLevels, fmt.internalFormat, tex->width, tex->height);
341 break;
342
343 case GL_TEXTURE_2D_ARRAY:
344 glTexStorage3D(tex->target, textureLevels, fmt.internalFormat, tex->width, tex->height, tex->depth);
345 break;
346
347 case GL_TEXTURE_3D:
348 glTexStorage3D(tex->target, textureLevels, fmt.internalFormat, tex->width, tex->height, tex->depth);
349 break;
350
351 case GL_TEXTURE_2D_MULTISAMPLE: [[fallthrough]];
352 default:
353 LOG_ERROR(logger, "Texture target #%04x cannot get data uploaded", tex->target);
354 break;
355 }
356}
357
359{
360 if (HandleIsValid(textureHandle)) {
361
362 // Make sure the texture isn't bound
363 for (GLuint i = 0; i < OpenGLES30::maxTexUnits; i++) {
364 if (context->texUnits[i].texture == textureHandle) {
365 if (context->activeTexUnit != i) {
366 context->activeTexUnit = i;
367 glActiveTexture(GL_TEXTURE0 + i);
368 }
369 glBindTexture(context->texUnits[i].target, 0);
370
371 context->texUnits[i].target = GL_TEXTURE_2D;
372 context->texUnits[i].texture = TextureHandle::NoHandle;
373 }
374 }
375
376 // If texture/renderbuffer is external, and NoDelete is not set, we have taken ownership
377 // of the resource and must release it.
378
379 TextureGLES30& texture = textures[textureHandle];
380 if (texture.fbo) {
381 glDeleteFramebuffers(1, &texture.fbo);
382 texture.fbo = 0;
383 }
384 if (texture.renderBuffer) {
385
386 // Don't release it if it is a borrowed renderbuffer
387 if ((texture.target != GL_RENDERBUFFER) || ((texture.flags & TextureFlags::NoDelete) == 0)) {
388 glDeleteRenderbuffers(1, &texture.renderBuffer);
389 }
390 texture.renderBuffer = 0;
391 }
392 // Don't release the texture if it is borrowed
393 if ((texture.textureId != 0) && ((texture.flags & TextureFlags::NoDelete) == 0)) {
394 glDeleteTextures(1, &texture.textureId);
395 }
396 if (texture.textureId != 0) {
397 textureMemoryConsumption -= texture.estimatedByteSize;
398 }
399 texture.textureId = 0;
400
401 textures.removeResource(textureHandle);
402 }
403}
404
405void Cogs::TexturesGLES30::releaseNativeTexture(TextureNativeHandle nativeHandle)
406{
407 GLuint id = (GLuint)(intptr_t)nativeHandle;
408 glDeleteTextures(1, &id);
409}
410
412{
414 LOG_WARNING_ONCE(logger, "loadSamplerState: ES30 does not support border color.");
415 }
416
417 GLuint sampler;
418 glGenSamplers(1, &sampler);
419
420 static const GLenum AddressModes[] = {
421 GL_CLAMP_TO_EDGE,
422 GL_REPEAT,
423 GL_MIRRORED_REPEAT,
424 GL_CLAMP_TO_EDGE
425 };
426 static_assert(sizeof(AddressModes) == sizeof(AddressModes[0]) * Cogs::SamplerState::AddressMode_Size);
427
428 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, AddressModes[state.addressModeS]);
429 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, AddressModes[state.addressModeT]);
430 glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, AddressModes[state.addressModeW]);
431
432 static const GLenum ComparisonFunctions[] = {
433 GL_NEVER,
434 GL_LESS,
435 GL_EQUAL,
436 GL_LEQUAL,
437 GL_GREATER,
438 GL_NOTEQUAL,
439 GL_GEQUAL,
440 GL_ALWAYS,
441 };
442 static_assert(sizeof(ComparisonFunctions) == sizeof(ComparisonFunctions[0]) * Cogs::SamplerState::ComparisonFunction_Size);
443
444 if (1 < state.maxAnisotropy) {
445 const GraphicsDeviceCapabilities& deviceCaps = caps->getDeviceCapabilities();
446 float maxAnisotropy = std::min(deviceCaps.MaxAnisotropy, float(state.maxAnisotropy));
447 if (1.f < maxAnisotropy) {
448 glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
449 }
450 }
451
452 switch (state.filter) {
454 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
455 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
456 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE);
457 break;
459 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
460 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
461 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE);
462 break;
464 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
465 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
466 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
467 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC, ComparisonFunctions[state.comparisonFunction]);
468 break;
469
471 glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
472 glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
473 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
474 glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC, ComparisonFunctions[state.comparisonFunction]);
475 break;
476 default:
477 assert(false);
478 }
479
480 return samplers.addResource(SamplerGLES30{ sampler });
481}
482
484{
485 if (HandleIsValid(samplerHandle)) {
486 const SamplerGLES30& sampler = samplers[samplerHandle];
487 glDeleteSamplers(1, &sampler.glName);
488 samplers.removeResource(samplerHandle);
489 }
490}
491
493{
494 if (viewDescription.layerIndex != 0) {
495 LOG_WARNING_ONCE(logger, "Views with nonzero layer index not supported, ignoring");
496 }
497 return views.addResource(viewDescription);
498}
499
501{
502 if (HandleIsValid(handle)) {
503 views.removeResource(handle);
504 }
505}
506
508{
509 if (HandleIsValid(textureHandle)) {
510 const TextureGLES30& tex = textures[textureHandle];
511 if (tex.target == GL_RENDERBUFFER) {
512 return reinterpret_cast<void*>(static_cast<size_t>(tex.renderBuffer));
513 }
514 return reinterpret_cast<void*>(static_cast<size_t>(tex.textureId));
515 }
516 return nullptr;
517}
518
520{
521 TextureGLES30* texture = context->bindTexture(textureHandle);
522 if (texture) {
523 glGenerateMipmap(texture->target);
524 }
525}
526
528{
529 std::vector<TextureHandle> handles;
530 for (TextureGLES30& texture : textures) {
531 handles.push_back(textures.getHandle(texture));
532 }
533 for (TextureHandle& handle : handles) {
534 releaseTexture(handle);
535 }
536}
Log implementation class.
Definition: LogManager.h:140
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
Contains device capabilities.
Definition: ICapabilities.h:67
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
static const Handle_t InvalidHandle
Represents an invalid handle.
Definition: Common.h:81
Encapsulates state for texture sampling in a state object.
Definition: SamplerState.h:12
ComparisonFunction comparisonFunction
Specifies the comparison function to use when applying a comparison sampler.
Definition: SamplerState.h:73
unsigned int maxAnisotropy
Specifies the maximum number of anisotropic samples to use when sampling a texture.
Definition: SamplerState.h:76
AddressMode addressModeW
Specifies the addressing mode along the W axis in texture coordinate space.
Definition: SamplerState.h:67
AddressMode addressModeS
Specifies the addressing mode along the S axis in texture coordinate space.
Definition: SamplerState.h:63
@ Border
Texture color is set to the border color when outside [0, 1] range.
Definition: SamplerState.h:23
@ ComparisonMinMagMipPoint
Comparison filter for depth sample comparisons using point sampling.
Definition: SamplerState.h:38
@ ComparisonMinMagMipLinear
Comparison filter for depth sample comparisons using linear interpolation sampling.
Definition: SamplerState.h:40
@ MinMagMipPoint
Point sampling for both minification and magnification.
Definition: SamplerState.h:33
@ MinMagMipLinear
Linear sampling for both minification and magnification.
Definition: SamplerState.h:35
FilterMode filter
Specifies the filter to use for texture sampling.
Definition: SamplerState.h:70
AddressMode addressModeT
Specifies the addressing mode along the T axis in texture coordinate space.
Definition: SamplerState.h:65
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
Definition: Flags.h:122
@ NoDelete
The ownership of the underlying texture resource is outside of cogs and cogs will not delete it.
Definition: Flags.h:136
@ GenerateMipMaps
The texture supports automatic mipmap generation performed by the graphics device.
Definition: Flags.h:124
Describes how to fetch data from a texture in shaders.
Definition: ITextures.h:13
uint32_t layerIndex
Index of the first layer (if array) to fetch from.
Definition: ITextures.h:17
void releaseNativeTexture(TextureNativeHandle nativeHandle) override
Release a native texture handle.
void releaseSamplerState(SamplerStateHandle handle)
Release the sampler state with the given handle.
void releaseTexture(TextureHandle textureHandle)
Release the texture with the given textureHandle.
void generateMipmaps(TextureHandle texureHandle)
Use the graphics device to generate mipmaps for the texture with the given texture handle.
void releaseResources()
Release all allocated texture resources.
TextureViewHandle createTextureView(TextureViewDescription &viewDescription) override
Create a texture view used to bind a limited view of the texture data to the rendering pipeline.
void * getNativeHandle(TextureHandle textureHandle) override
Get the device-specific handle (D3D texture pointer, OpenGL texture ID etc) associated with the given...
TextureHandle loadTexture(const TextureDescription &desc, const TextureData *data)
Load a texture from the given description.
void releaseTextureView(const TextureViewHandle &handle) override
Release the given texture view.
SamplerStateHandle loadSamplerState(const SamplerState &state)
Load a sampler state object.