1#include "RenderTexture.h"
3#include "Rendering/IGraphicsDevice.h"
4#include "Rendering/ITextures.h"
5#include "Rendering/IContext.h"
6#include "Rendering/IRenderTargets.h"
8#include "Foundation/Logging/Logger.h"
9#include "Foundation/BitTwiddling/PowerOfTwo.h"
11#include "Resources/Texture.h"
15#include "RenderTarget.h"
22 uint32_t lzcnt(uint32_t x)
24 if (x == 0u)
return (32u);
26 if ((x >> 16) == 0) { n += 16u; x = x << 16; }
27 if ((x >> 24) == 0) { n += 8u; x = x << 8; }
28 if ((x >> 28) == 0) { n += 4u; x = x << 4; }
29 if ((x >> 30) == 0) { n += 2u; x = x << 2; }
35Cogs::Core::RenderTexture::RenderTexture()
37 type = RenderResourceType::RenderTexture;
46 ITextures* textures = device->getTextures();
49 const bool dimensionsChanged = texture->description.width != description.width ||
50 texture->description.target != description.target ||
51 texture->description.height != description.height ||
52 texture->description.depth != description.depth ||
53 texture->description.format != description.format ||
54 texture->description.layers != description.layers ||
55 texture->description.levels != description.levels ||
56 texture->description.faces != description.faces ||
57 texture->description.samples != description.samples ||
60 if (!dimensionsChanged) {
61 if (!isRenderTarget && !isDepthTarget) {
62 if (!texture->storage.data.empty()) {
67 .width = description.width,
68 .height = description.height,
69 .depth = description.depth,
71 TextureData textureData(texture->storage.getData(), extent, description.layers, description.faces, description.levels, description.format);
72 textures->uploadTextureData(textureHandle, textureData);
75 device->getImmediateContext()->updateSubTexture(textureHandle, 0, texture->storage.getData());
78 textures->generateMipmaps(textureHandle);
86 textures->releaseTexture(textureHandle);
90 if (texture->externalHandle) {
92 TextureData textureData;
93 textureData.initExternal(texture->externalHandle);
94 textureHandle = textures->loadTexture(texture->description, &textureData);
95 textures->annotate(textureHandle, getName());
97 else if (texture->ownsExternalTexture.value) {
98 LOG_TRACE(logger,
"Clearing render texture handle");
104 textureHandle = textures->loadTexture(texture->description, (isRenderTarget || isDepthTarget || !texture->storage.data.size()) ?
nullptr : &texture->storage);
105 textures->annotate(textureHandle, getName());
108 description = texture->description;
110 texture->clearData();
113 LOG_ERROR(logger,
"Failed to create texture.");
120 incrementGeneration();
126void Cogs::Core::RenderTexture::release(Renderer * renderer)
128 auto device = renderer->getDevice();
131 renderer->getRenderResources().releaseResource(renderTarget);
132 renderTarget =
nullptr;
136 renderer->getRenderResources().releaseResource(depthTexture);
137 depthTexture =
nullptr;
140 auto textures = device->getTextures();
142 for (
auto & view : views) {
143 textures->releaseTextureView(view.second);
149 textures->releaseTexture(textureHandle);
157void Cogs::Core::RenderTexture::update(Renderer * renderer)
159 auto device = renderer->getDevice();
160 auto textures = device->getTextures();
163 auto targetSize = renderer->getSize();
165 if (isOverride())
return;
168 uint32_t targetWidth = (uint32_t)(scale * (
float)targetSize.x);
169 uint32_t targetHeight = (uint32_t)(scale * (
float)targetSize.y);
170 uint32_t targetSamples = 0;
173 if (sizeSource->getType() == RenderResourceType::RenderTexture) {
174 targetWidth =
static_cast<RenderTexture *
>(sizeSource)->description.width;
175 targetHeight =
static_cast<RenderTexture *
>(sizeSource)->description.height;
176 targetSamples =
static_cast<RenderTexture *
>(sizeSource)->description.samples;
179 targetWidth =
static_cast<RenderTarget *
>(sizeSource)->width;
180 targetHeight =
static_cast<RenderTarget *
>(sizeSource)->height;
181 targetSamples =
static_cast<RenderTarget *
>(sizeSource)->samples;
184 else if (width != 0 && height != 0) {
185 targetWidth =
static_cast<int>(width);
186 targetHeight =
static_cast<int>(height);
187 targetSamples =
static_cast<uint32_t
>(samples);
190 targetSamples =
static_cast<uint32_t
>(samples);
194 uint32_t maxSize =
static_cast<uint32_t
>(std::max(targetWidth, targetHeight));
195 uint32_t maxLevels = 31 - std::min(31u, lzcnt(maxSize));
196 assert((maxSize == 0) || ((1u << maxLevels) <= maxSize));
197 assert(maxSize <= (1u << (maxLevels + 1)));
198 uint32_t targetLevels = std::min(maxLevels,
static_cast<uint32_t
>(levels.getValue() == 0 ? 1 : levels.getValue()));
201 uint32_t targetFaces = 1;
202 if (faces == 6) targetFaces = 6;
204 uint32_t targetLayers =
static_cast<uint32_t
>(layers.getValue() == 0 ? 1 : layers.getValue());
206 if (!targetWidth || !targetHeight)
return;
208 if (targetWidth == description.width &&
209 targetHeight == description.height &&
210 targetLevels == description.levels &&
211 targetFaces == description.faces &&
212 targetLayers == description.layers &&
213 targetSamples == description.samples)
return;
217 description.width = targetWidth;
218 description.height = targetHeight;
219 description.levels = targetLevels;
220 description.faces = targetFaces;
221 description.layers = targetLayers;
222 description.samples = targetSamples;
223 if (description.target == ResourceDimensions::Texture2D && description.samples > 1) {
224 description.target = ResourceDimensions::Texture2DMS;
227 textureHandle = textures->loadTexture(description,
nullptr);
229 textures->annotate(textureHandle, getName());
231 incrementGeneration();
Log implementation class.
ActivationResult
Defines results for resource activation.
@ Success
Resource activated successfully.
@ Failure
Resource activation failed.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ OpenGL20
Graphics device using OpenGL, supporting at least OpenGL 2.0.
static const Handle_t NoHandle
Represents a handle to nothing.
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
@ RenderTarget
The texture can be used as a render target and drawn into.
@ GenerateMipMaps
The texture supports automatic mipmap generation performed by the graphics device.