Cogs.Core
MipLevelsTask.cpp
1#include "MipLevelsTask.h"
2
3#include "Platform/Instrumentation.h"
4
5#include "Rendering/IBuffers.h"
6#include "Rendering/ICapabilities.h"
7#include "Rendering/IContext.h"
8#include "Rendering/IGraphicsDevice.h"
9#include "Rendering/ITextures.h"
10#include "Rendering/SamplerState.h"
11
12#include "Renderer/Renderer.h"
13#include "Renderer/RenderTarget.h"
14#include "Renderer/RenderTexture.h"
15
16#include "Resources/VertexFormats.h"
17
18#include "Utilities/Parsing.h"
19
20using namespace Cogs;
21
22namespace
23{
24 struct MipLevelsParameter
25 {
26 glm::vec2 srcTexelSize;
27 glm::vec2 dstTexelSize;
28 int srcLevel;
29 int dstLevel;
30 };
31}
32void Cogs::Core::MipLevelsTask::initialize(RenderTaskContext* context)
33{
34 PostProcessTask::initialize(context);
35}
36
37void Cogs::Core::MipLevelsTask::initialize(RenderTaskContext * context, const RenderTaskDefinition& taskDefinition)
38{
39 PostProcessTask::initialize(context, taskDefinition);
40 if (effect == nullptr || !HandleIsValid(effect->handle)) return;
41
42 auto device = context->renderer->getDevice();
43 auto effects = device->getEffects();
44 auto buffers = device->getBuffers();
45
46 parameterHandle = buffers->loadBuffer(nullptr, sizeof(MipLevelsParameter), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
47 parameterBufferBinding = effects->getConstantBufferBinding(effect->handle, "MipLevelsParameter");
48}
49
50void Cogs::Core::MipLevelsTask::cleanup(RenderTaskContext * context)
51{
52 auto device = context->renderer->getDevice();
53 auto buffers = device->getBuffers();
54 buffers->releaseBuffer(parameterHandle);
55 PostProcessTask::cleanup(context);
56}
57
58void Cogs::Core::MipLevelsTask::apply(RenderTaskContext * context)
59{
60 DynamicRenderInstrumentationScope(context->device->getImmediateContext(), SCOPE_RENDERING, "MipLevelsTask", (std::string("MipLevelsTask<") + name + ">::apply").c_str());
61
62 if (effect == nullptr || !HandleIsValid(effect->handle)) return;
63
64 auto device = context->renderer->getDevice();
65 auto deviceContext = device->getImmediateContext();
66 auto effects = device->getEffects();
67
68 auto renderTarget = output.get(RenderResourceType::RenderTarget)->renderTarget;
69 auto targetSource = renderTarget->textures[0];
70
71 std::string targetSourceKey;
72 for (auto & p : properties) {
73 if (p.definition->type == ParsedDataType::Texture2D) {
74 auto inputSource = input.get(p.definition->value);
75 RenderTexture* tex = nullptr;
76 if (inputSource->type == RenderResourceType::RenderTexture) {
77 tex = inputSource->renderTexure;
78 }
79 else if (inputSource->type == RenderResourceType::RenderTarget) {
80 tex = inputSource->renderTarget->textures[0];
81 }
82 if (tex) {
83 targetSourceKey = p.definition->key;
84 }
85 }
86 }
87
88 size_t maxLevel = std::max(size_t(1u), renderTarget->mipLevelViews.size());
89 if (sizes.size() != maxLevel || sizes[0].x != renderTarget->width || sizes[0].y != renderTarget->height) {
90 sizes.resize(maxLevel);
91 sizes[0] = glm::ivec2(renderTarget->width, renderTarget->height);
92 for (uint32_t i = 1; i < maxLevel; i++) {
93 sizes[i] = glm::ivec2(std::max(1, sizes[i - 1].x / 2), std::max(1, sizes[i - 1].y / 2));
94 }
95 }
96
98 if (!targetSourceKey.empty()) {
99 SamplerState ss;
100 std::memset(&ss, 0, sizeof(SamplerState));
105
106 targetSourceHandle = effects->getTextureBinding(effect->handle, targetSourceKey, texUnit);
107 deviceContext->setSamplerState(targetSourceKey + "Sampler", texUnit, context->states->getSamplerState(ss));
108
109 texUnit++;
110 }
111
112 if (!HandleIsValid(targetSourceHandle)) {
113 //TODO: Log warning
114 return;
115 }
116
117 size_t currentFirstLevel = std::min(maxLevel - 1u, static_cast<size_t>(firstLevel));
118 size_t currentLastLevel = std::min(maxLevel - 1u, static_cast<size_t>(lastLevel));
119 if (currentFirstLevel < currentLastLevel) {
120 for (size_t level = currentFirstLevel; level < currentLastLevel; level++) {
121 draw(context, renderTarget, targetSource, targetSourceHandle, level, level + 1);
122 }
123 } else if (currentLastLevel < currentFirstLevel) {
124 for (size_t level = currentFirstLevel; currentLastLevel < level; level--) {
125 draw(context, renderTarget, targetSource, targetSourceHandle, level, level - 1);
126 }
127 }
128}
129
130void Cogs::Core::MipLevelsTask::draw(RenderTaskContext * context,
131 RenderTarget * renderTarget,
132 RenderTexture * targetSource,
133 TextureBindingHandle &targetSourceHandle,
134 const size_t srcLevel, const size_t dstLevel)
135{
136 auto device = context->renderer->getDevice();
137 auto deviceContext = device->getImmediateContext();
138
139 if(device->getCapabilities()->getDeviceCapabilities().RenderPass){
140 RenderPassInfo info;
141 info.renderTargetHandle = renderTarget->mipLevelViews[dstLevel];
142 info.depthStencilHandle = DepthStencilHandle::NoHandle;
143 {
144 uint32_t i = 0;
145 info.loadOp[i] = clearColor ? LoadOp::Clear : LoadOp::Load;
146 info.storeOp[i] = StoreOp::Store;
147 glm::vec4 color;
148 if (clearToDefault) {
149 color = context->renderer->getBackgroundColor();
150 }
151 else{
152 color = renderTarget->getClearColor();
153 }
154 info.clearValue[i][0] = color[0];
155 info.clearValue[i][1] = color[1];
156 info.clearValue[i][2] = color[2];
157 info.clearValue[i][3] = color[3];
158 }
159 info.depthLoadOp = LoadOp::Undefined;
160 info.depthStoreOp = StoreOp::Undefined;
161 info.depthClearValue = context->renderer->getClearDepth();
162 deviceContext->beginRenderPass(info);
163 }
164 else{
165 deviceContext->setRenderTarget(renderTarget->mipLevelViews[dstLevel], DepthStencilHandle::NoHandle);
166 }
167
168 deviceContext->setEffect(effect->handle);
169 deviceContext->setDepthStencilState(context->states->noDepthStencilStateHandle);
170 deviceContext->setRasterizerState(context->states->defaultRasterizerStateHandle);
171
172 for (size_t i = 0; i < 4; ++i) {
173 if (HandleIsValid(samplerStateBindings[i])) {
174 deviceContext->setSamplerState(samplerStateBindings[i], samplerStates[i]);
175 }
176 }
177
178 setProperties(context, targetSource);
179
180 {
181 MappedBuffer<MipLevelsParameter> parameters(deviceContext, parameterHandle, MapMode::WriteDiscard);
182
183 if (parameters) {
184 parameters->srcTexelSize = glm::vec2(1.f) / glm::vec2(sizes[srcLevel]);
185 parameters->dstTexelSize = glm::vec2(1.f) / glm::vec2(sizes[dstLevel]);
186 parameters->srcLevel = static_cast<int>(srcLevel);
187 parameters->dstLevel = static_cast<int>(dstLevel);
188 }
189 }
190
191 deviceContext->setConstantBuffer(parameterBufferBinding, parameterHandle);
192
193 TextureViewDescription textureViewDesc = {};
194 textureViewDesc.texture = targetSource->textureHandle;
195 textureViewDesc.layerIndex = 0;
196 textureViewDesc.numLayers = 1;
197 textureViewDesc.levelIndex = static_cast<uint32_t>(srcLevel);
198 textureViewDesc.numLevels = 1;
199
200 size_t code = textureViewDesc.hash();
201
202 auto found = targetSource->views.find(code);
203
204 Cogs::TextureViewHandle textureView;
205 if (found == targetSource->views.end()) {
206 textureView = device->getTextures()->createTextureView(textureViewDesc);
207 targetSource->views.insert({ code, textureView });
208 } else {
209 textureView = found->second;
210 }
211
212 deviceContext->setTexture(targetSourceHandle, textureView);
213 deviceContext->setViewport(0, 0, (float)sizes[dstLevel].x, (float)sizes[dstLevel].y);
214
215 deviceContext->setVertexBuffers(&context->states->fullScreenTriangle, 1);
216 deviceContext->setIndexBuffer(IndexBufferHandle::NoHandle);
217 deviceContext->setInputLayout(inputLayout);
218
219 deviceContext->draw(PrimitiveType::TriangleList, 0, 3);
220
221 if(device->getCapabilities()->getDeviceCapabilities().RenderPass){
222 deviceContext->endRenderPass();
223 }
224}
225
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
@ TriangleList
List of triangles.
@ Write
The buffer can be mapped and written to by the CPU after creation.
Definition: Flags.h:50
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
Definition: Flags.h:72
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
@ WriteDiscard
Write access. When unmapping the graphics system will discard the old contents of the resource.
Definition: Flags.h:103
Provides RAII style mapping of a buffer resource.
Definition: IBuffers.h:160
Encapsulates state for texture sampling in a state object.
Definition: SamplerState.h:12
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
@ Clamp
Texture coordinates are clamped to the [0, 1] range.
Definition: SamplerState.h:17
@ 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
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
uint32_t numLayers
Number of array layers available.
Definition: ITextures.h:19
uint32_t numLevels
Number of mipmap levels available.
Definition: ITextures.h:23
uint32_t levelIndex
First mipmap level to fetch data from.
Definition: ITextures.h:21
TextureHandle texture
Texture.
Definition: ITextures.h:15
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30