Cogs.Core
RenderTarget.cpp
1#include "RenderTarget.h"
2
3#include "Rendering/ITextures.h"
4#include "Rendering/IRenderTargets.h"
5#include "Rendering/ISwapChain.h"
6
7#include "Tasks/RenderTask.h"
8
9#include "Renderer.h"
10#include "RenderTexture.h"
11
12#include "Foundation/HashSequence.h"
13#include "Foundation/Logging/Logger.h"
14
15namespace
16{
17 Cogs::Logging::Log logger = Cogs::Logging::getLogger("RenderTarget");
18}
19
20void Cogs::Core::RenderTarget::update(Renderer * renderer)
21{
22 auto device = renderer->getDevice();
23 auto targets = device->getRenderTargets();
24
25 if (!checkUpdate()) return;
26
27 release(renderer);
28
29 size_t textureCount = textures.size();
30
31 // Hooks for external textures/targets
32 // -----------------------------------
33
34 if (textureCount == 1) {
35
36 // Override implies that the texture is managed externally. We make a render and depth targets using those textures and exit.
37 if(textures[0]->isOverride()) {
38
39 RenderTexture* texture = textures[0];
40 for (size_t i = 0; i < static_cast<size_t>(texture->count); ++i) {
41
42 renderTargetHandles[i] = targets->createRenderTarget(&texture->textureHandles[i], 1);
43 targets->annotate(renderTargetHandles[i], getName().to_string() + " color target " + std::to_string(i));
44
45 depthTargetHandles[i] = depth ? targets->createDepthStencilTarget(renderTargetHandles[i], depth->textureHandle) : targets->createDepthStencilTarget(renderTargetHandles[i]);
46 targets->annotate(depthTargetHandles[i], getName().to_string() + " depth target " + std::to_string(i));
47 }
48
49 renderTargetHandle = renderTargetHandles[0];
50 depthTargetHandle = depthTargetHandles[0];
51 width = texture->description.width;
52 height = texture->description.height;
53 samples = texture->description.samples;
54 return;
55 }
56
57 // Texture is just a proxy for a swap chain
58 if (textures[0]->swapChain) {
59 Cogs::ISwapChain* swapChain = textures[0]->swapChain;
60 renderTargetHandle = swapChain->getRenderTarget();
61 depthTargetHandle = swapChain->getDepthStencil();
62 width = swapChain->getWidth();
63 height = swapChain->getHeight();
64 samples = swapChain->getSamples();
65 return;
66 }
67 }
68
69 // Normal rendertarget with cogs textures
70 // --------------------------------------
71
72 // Populated if enabled on color, used by color and depth.
73 Cogs::MultiViewDescription multiViewDesc{};
74
75 // No textures
76 if (textureCount == 0) {
77 renderTargetHandle = RenderTargetHandle::NoHandle;
78 }
79
80 // Single color texture, support for mipmaps
81 else if (textureCount == 1) {
82
83 size_t levelViews = std::max(1u, std::min(textures[0]->description.levels, static_cast<uint32_t>(levels)));
84
85 RenderTargetViewDescription view = {
86 .texture = textures[0]->textureHandle,
87 .layerIndex = layerIndex,
88 .numLayers = numLayers,
89 .levelIndex = 0
90 };
91 mipLevelViews.resize(levelViews);
92 for (size_t l = 0; l < levelViews; l++) {
93 view.levelIndex = uint8_t(l);
94
95 if (1 < multiViewCount) {
96 multiViewDesc.baseIndex = multiViewBaseIndex;
97 multiViewDesc.count = multiViewCount;
98 multiViewDesc.samples = multiViewSamples;
99 mipLevelViews[l] = targets->createRenderTarget(&view, 1, multiViewDesc);
100 }
101 else {
102 mipLevelViews[l] = targets->createRenderTarget(&view, 1);
103 }
104 targets->annotate(mipLevelViews[l], getName().to_string() + " view " + std::to_string(l));
105 }
106 renderTargetHandle = mipLevelViews[0];
107
108 }
109
110 // Multiple textures, no mipmap support for now.
111 else {
112
113 std::vector<Cogs::TextureHandle> handles;
114 for (auto& texture : textures) {
115 if (HandleIsValid(texture->textureHandle)) {
116 handles.push_back(texture->textureHandle);
117 }
118 }
119
120 if (!handles.empty()) {
121 mipLevelViews.resize(1);
122 mipLevelViews[0] = targets->createRenderTarget(handles.data(), handles.size());
123 targets->annotate(mipLevelViews[0], getName().to_string());
124 renderTargetHandle = mipLevelViews[0];
125 }
126 else if (textures.size() == 1) {
127 if (textures[0]->swapChain) {
128 renderTargetHandle = textures[0]->swapChain->getRenderTarget();
129 }
130 }
131 }
132
133
134 if (depth && HandleIsValid(depth->textureHandle)) {
135 DepthStencilViewDescription depthTextureView = {};
136 depthTextureView.texture = depth->textureHandle;
137 depthTextureView.layerIndex = uint16_t(depthLayerIndex);
138 depthTextureView.numLayers = 1;
139 if (multiViewDesc.count) {
140 depthTargetHandle = targets->createDepthStencilTarget(renderTargetHandle, depthTextureView, multiViewDesc);
141 }
142 else {
143 depthTargetHandle = targets->createDepthStencilTarget(renderTargetHandle, depthTextureView);
144 }
145 targets->annotate(depthTargetHandle, getName().to_string());
146 }
147 else {
148 depthTargetHandle = DepthStencilHandle::NoHandle;
149 }
150
151 if (textures.size()) {
152 width = textures[0]->description.width;
153 height = textures[0]->description.height;
154 samples = textures[0]->description.samples;
155 }
156 else if (depth) {
157 width = depth->description.width;
158 height = depth->description.height;
159 samples = depth->description.samples;
160 }
161
162}
163
164void Cogs::Core::RenderTarget::release(Renderer * renderer)
165{
166 if ((textures.size() == 1) && textures[0]->swapChain) {
167 renderTargetHandle = RenderTargetHandle::NoHandle;
168 depthTargetHandle = DepthStencilHandle::NoHandle;
169 }
170 else {
171 auto device = renderer->getDevice();
172 auto renderTargets = device->getRenderTargets();
173
174 if (HandleIsValid(depthTargetHandle)) {
175 renderTargets->releaseDepthStencilTarget(depthTargetHandle);
176 depthTargetHandle = DepthStencilHandle::NoHandle;
177 }
178
179 if (!mipLevelViews.empty()) {
180 for (auto & h : mipLevelViews) {
181 if (HandleIsValid(h)) {
182 renderTargets->releaseRenderTarget(h);
183 }
184 }
185 mipLevelViews.clear();
186 }
187 else if (HandleIsValid(renderTargetHandle)) {
188 renderTargets->releaseRenderTarget(renderTargetHandle);
189 renderTargetHandle = RenderTargetHandle::NoHandle;
190 }
191 }
192}
193
194Cogs::TextureHandle Cogs::Core::RenderTarget::get(const std::string & name)
195{
196 for (auto & t : textures) {
197 if (t->getName() == name) return t->textureHandle;
198 }
199
201}
202
203bool Cogs::Core::RenderTarget::checkUpdate()
204{
205 if (isOverride()) return false;
206
207 size_t generationHash = hash();
208 for (auto & t : textures) {
209 generationHash = hash(t->getGeneration(), generationHash);
210 }
211 if (depth) {
212 generationHash = hash(depth->getGeneration(), generationHash);
213 }
214 generationHash = hash(static_cast<uint32_t>(this->levels), generationHash);
215
216 if (generationHash != this->generationHash) {
217 this->generationHash = generationHash;
218 return true;
219 }
220 return false;
221}
virtual int getWidth() const =0
Returns the pixel width of this swap chain.
virtual int getHeight() const =0
Returns the pixel height of this swap chain.
virtual const RenderTargetHandle & getRenderTarget() const =0
Returns the render target managed by this swap chain.
virtual const DepthStencilHandle & getDepthStencil() const =0
Returns the depth stencil managed by this swap chain.
virtual int getSamples() const =0
Returns the number of samples this swap chain has.
Log implementation class.
Definition: LogManager.h:139
std::string to_string() const
String conversion method.
Definition: StringView.cpp:9
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
Definition: LogManager.h:180
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Definition: HashFunctions.h:62
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:77
Describes multiview framebuffer layout.