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;
40Cogs::Core::ActivationResult Cogs::Core::RenderTexture::update(Texture * texture, IGraphicsDevice * device, RenderResources * renderResources)
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);
84 release(device, renderResources);
86 if (texture->externalHandle) {
88 TextureData textureData;
89 textureData.initExternal(texture->externalHandle);
90 textureHandle = textures->loadTexture(texture->description, &textureData);
91 textures->annotate(textureHandle, getName());
93 else if (texture->ownsExternalTexture.value) {
94 LOG_TRACE(logger,
"Clearing render texture handle");
100 textureHandle = textures->loadTexture(texture->description, (isRenderTarget || isDepthTarget || !texture->storage.data.size()) ?
nullptr : &texture->storage);
101 textures->annotate(textureHandle, getName());
104 description = texture->description;
106 texture->clearData();
109 LOG_ERROR(logger,
"Failed to create texture.");
116 incrementGeneration();
122void Cogs::Core::RenderTexture::release(IGraphicsDevice * device, RenderResources * resources)
125 resources->releaseResource(renderTarget);
126 renderTarget =
nullptr;
129 resources->releaseResource(resolveTarget);
130 resolveTarget =
nullptr;
134 resources->releaseResource(depthTexture);
135 depthTexture =
nullptr;
138 auto textures = device->getTextures();
140 for (
auto & view : views) {
141 textures->releaseTextureView(view.second);
146 textures->releaseTexture(textureHandle);
151void Cogs::Core::RenderTexture::release(Renderer * renderer)
153 release(renderer->getDevice(), &renderer->getRenderResources());
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 =
static_cast<uint32_t
>(samples);
173 if (sizeSource->getType() == RenderResourceType::RenderTexture) {
174 targetWidth =
static_cast<RenderTexture *
>(sizeSource)->description.width;
175 targetHeight =
static_cast<RenderTexture *
>(sizeSource)->description.height;
178 targetWidth =
static_cast<RenderTarget *
>(sizeSource)->width;
179 targetHeight =
static_cast<RenderTarget *
>(sizeSource)->height;
183 int iw =
static_cast<int>(width);
184 int ih =
static_cast<int>(height);
185 if((description.width != (uint32_t)std::max(iw, 2)) && iw < 2){
186 LOG_WARNING(logger,
"Render texture, width %d < 2. (Clamping to 2).", iw);
188 if((description.height != (uint32_t)std::max(ih, 2)) && ih < 2){
189 LOG_WARNING(logger,
"Render texture, height %d < 2. (Clamping to 2).", ih);
191 targetWidth = std::max(iw, 2);
192 targetHeight = std::max(ih, 2);
196 uint32_t maxSize =
static_cast<uint32_t
>(std::max(targetWidth, targetHeight));
197 uint32_t maxLevels = 31 - std::min(31u, lzcnt(maxSize));
198 assert((maxSize == 0) || ((1u << maxLevels) <= maxSize));
199 assert(maxSize <= (1u << (maxLevels + 1)));
200 uint32_t targetLevels = std::min(maxLevels,
static_cast<uint32_t
>(levels.getValue() == 0 ? 1 : levels.getValue()));
203 uint32_t targetFaces = 1;
204 if (faces == 6) targetFaces = 6;
206 uint32_t targetLayers =
static_cast<uint32_t
>(layers.getValue() == 0 ? 1 : layers.getValue());
208 if (!targetWidth || !targetHeight)
return;
210 if (targetWidth == description.width &&
211 targetHeight == description.height &&
212 targetLevels == description.levels &&
213 targetFaces == description.faces &&
214 targetLayers == description.layers &&
215 targetSamples == description.samples)
return;
219 description.width = targetWidth;
220 description.height = targetHeight;
221 description.levels = targetLevels;
222 description.faces = targetFaces;
223 description.layers = targetLayers;
224 description.samples = targetSamples;
225 if (description.target == ResourceDimensions::Texture2D && description.samples > 1) {
226 description.target = ResourceDimensions::Texture2DMS;
228 if (description.target == ResourceDimensions::Texture2DMS && description.samples == 1) {
229 description.target = ResourceDimensions::Texture2D;
232 textureHandle = textures->loadTexture(description,
nullptr);
234 textures->annotate(textureHandle, getName());
236 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.