1#include "Foundation/Logging/Logger.h"
3#include "Rendering/ICapabilities.h"
7#include "Systems/Core/LightSystem.h"
8#include "Systems/Core/EnvironmentSystem.h"
10#include "Resources/Mesh.h"
11#include "Resources/Skeleton.h"
12#include "Resources/Animation.h"
13#include "Resources/BasicBlueNoiseManager.h"
14#include "RenderStateUpdater.h"
15#include "RenderList.h"
17#include "Tasks/RenderTask.h"
18#include "Tasks/GenerateListTask.h"
20#include "Resources/TextureManager.h"
28void Cogs::Core::applyMaterialProperties(
const DrawContext * drawContext,
30 const ConstantBufferBindingHandle & bufferBinding,
31 const BufferHandle & constantBuffer)
33 auto deviceContext = drawContext->deviceContext;
35 deviceContext->setConstantBuffer(bufferBinding, constantBuffer);
39void Cogs::Core::updateSceneBindings(
const DrawContext * drawContext,
const CameraData * ,
const EffectBinding * bindings)
41 assert(drawContext->taskContext &&
"Invalid rendering context.");
43 updateSceneBindings(drawContext->taskContext, bindings);
46void Cogs::Core::updateSceneBindings(
const RenderTaskContext * taskContext,
const EffectBinding * bindings)
48 const EngineBuffers* engineBuffers = &taskContext->renderer->getEngineBuffers();
49 IGraphicsDevice* device = taskContext->renderer->getDevice();
50 IContext* deviceContext = device->getImmediateContext();
53 deviceContext->setConstantBuffer(bindings->sceneBufferBinding, engineBuffers->sceneBufferHandle);
56 deviceContext->setConstantBuffer(bindings->viewBufferBinding, engineBuffers->viewBufferHandle);
60 auto& blueNoiseManager = taskContext->context->blueNoiseManager;
61 blueNoiseManager->enable();
62 TextureHandle blueNoise = blueNoiseManager->getBlueNoiseHandle(
false)->texture;
63 RenderTexture * blueNoiseTexture = taskContext->renderer->getRenderResources().getRenderTexture(blueNoise);
64 if (blueNoiseTexture) {
65 deviceContext->setTexture(bindings->blueNoise, blueNoiseTexture->textureHandle);
69 auto& blueNoiseManager = taskContext->context->blueNoiseManager;
70 blueNoiseManager->enable();
71 TextureHandle blueNoise = blueNoiseManager->getBlueNoiseHandle(
true)->texture;
72 RenderTexture * blueNoiseTexture = taskContext->renderer->getRenderResources().getRenderTexture(blueNoise);
73 if (blueNoiseTexture) {
74 deviceContext->setTexture(bindings->blueNoiseStable, blueNoiseTexture->textureHandle);
79void Cogs::Core::updateEnvironmentBindings(
const DrawContext * drawContext,
const EffectBinding * bindings)
81 auto deviceContext = drawContext->deviceContext;
82 auto lightSystem = drawContext->context->lightSystem;
85 deviceContext->setConstantBuffer(bindings->lightBufferBinding,
86 drawContext->renderer->getEngineBuffers().lightBufferHandle);
89 if (!drawContext->permutation->isShadowPass() &&
HandleIsValid(bindings->shadowBufferBinding)) {
91 deviceContext->setConstantBuffer(bindings->shadowBufferBinding, drawContext->engineBuffers->shadowBufferHandle);
94 RenderTexture * shadowTexture = drawContext->renderer->getRenderResources().getRenderTexture(lightSystem->cascadeArray);
97 deviceContext->setTexture(bindings->shadowArrayBinding, shadowTexture->textureHandle);
98 deviceContext->setSamplerState(
"", 1, drawContext->taskContext->states->shadowSampler);
102 RenderTexture * shadowTexture = drawContext->renderer->getRenderResources().getRenderTexture(lightSystem->cascadeArray);
105 deviceContext->setTexture(bindings->shadowArrayBinding_1, shadowTexture->textureHandle);
106 deviceContext->setSamplerState(
"", 1, drawContext->taskContext->states->shadowSampler);
111 RenderTexture * shadowTexture = drawContext->renderer->getRenderResources().getRenderTexture(lightSystem->cubeArray);
114 deviceContext->setTexture(bindings->shadowCubeArrayBinding, shadowTexture->textureHandle);
115 deviceContext->setSamplerState(
"", 2, drawContext->taskContext->states->shadowSampler);
119 auto shadowTexture = drawContext->renderer->getRenderResources().getRenderTexture(lightSystem->cubeArray);
122 deviceContext->setTexture(bindings->shadowCubeArrayBinding_1, shadowTexture->textureHandle);
123 deviceContext->setSamplerState(
"", 2, drawContext->taskContext->states->shadowSampler);
129 deviceContext->setSamplerState(bindings->shadowSamplerBinding, drawContext->taskContext->states->shadowSampler);
132 deviceContext->setSamplerState(bindings->shadowArraySamplerBinding, drawContext->taskContext->states->shadowSampler);
134 if (
HandleIsValid(bindings->shadowCubeArraySamplerBinding)) {
135 deviceContext->setSamplerState(bindings->shadowCubeArraySamplerBinding, drawContext->taskContext->states->shadowSampler);
140 deviceContext->setSamplerState(bindings->shadowSamplerBinding, drawContext->taskContext->states->shadowSampler);
144 auto environmentComponent = drawContext->cameraData->environment.resolveComponent<EnvironmentComponent>();
146 if (environmentComponent) {
147 if (environmentComponent->isSubmerged(drawContext->cameraData)) {
149 if (environmentComponent->subseaRadiance) {
150 RenderTexture * subseaRadianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->subseaRadiance);
151 if (subseaRadianceTexture) {
152 if (subseaRadianceTexture->description.target != ResourceDimensions::TextureCube) {
153 static int count = 0;
155 LOG_ERROR(logger,
"environment.subseaRadiance is not a cube texture.");
161 deviceContext->setTexture(bindings->skyBinding, subseaRadianceTexture->textureHandle);
164 deviceContext->setTexture(bindings->radianceBinding, subseaRadianceTexture->textureHandle);
167 deviceContext->setTexture(bindings->irradianceBinding, subseaRadianceTexture->textureHandle);
170 deviceContext->setTexture(bindings->ambientIrradianceBinding, subseaRadianceTexture->textureHandle);
176 if (environmentComponent->skyDome &&
HandleIsValid(bindings->skyBinding)) {
178 if (RenderTexture * skyTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->skyDome); skyTexture) {
180 if (skyTexture->description.target != ResourceDimensions::TextureCube) {
181 static int warningCount = 0;
182 if (warningCount < 10) {
183 LOG_ERROR(logger,
"environment.skyDome is not a cube texture.");
188 deviceContext->setTexture(bindings->skyBinding, skyTexture->textureHandle);
194 if (environmentComponent->radiance &&
HandleIsValid(bindings->radianceBinding)) {
196 if (RenderTexture * radianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->radiance); radianceTexture) {
198 if (radianceTexture->description.target != ResourceDimensions::TextureCube) {
199 static int warningCount = 0;
200 if (warningCount < 10) {
201 LOG_ERROR(logger,
"environment.radiance is not a cube texture.");
206 deviceContext->setTexture(bindings->radianceBinding, radianceTexture->textureHandle);
212 if (environmentComponent->irradiance &&
HandleIsValid(bindings->irradianceBinding)) {
214 if (RenderTexture * irradianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->irradiance); irradianceTexture) {
216 if (irradianceTexture->description.target != ResourceDimensions::TextureCube) {
217 static int warningCount = 0;
218 if (warningCount < 10) {
219 LOG_ERROR(logger,
"environment.irradiance is not a cube texture.");
224 deviceContext->setTexture(bindings->irradianceBinding, irradianceTexture->textureHandle);
229 if (environmentComponent->ambientIrradiance &&
HandleIsValid(bindings->ambientIrradianceBinding)) {
230 RenderTexture * ambientIrradianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->ambientIrradiance);
231 if (ambientIrradianceTexture) {
233 if (ambientIrradianceTexture->description.target != ResourceDimensions::TextureCube) {
234 static int warningCount = 0;
235 if (warningCount < 10) {
236 LOG_ERROR(logger,
"environment.ambientIrradiance is not a cube texture.");
241 deviceContext->setTexture(bindings->ambientIrradianceBinding, ambientIrradianceTexture->textureHandle);
245 if (environmentComponent->brdfLUT &&
HandleIsValid(bindings->brdfLUTBinding)) {
246 RenderTexture* brdfLUTTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->brdfLUT);
247 if (brdfLUTTexture) {
249 if (brdfLUTTexture->description.target != ResourceDimensions::Texture2D) {
250 static int warningCount = 0;
251 if (warningCount < 10) {
252 LOG_ERROR(logger,
"environment.brdfLUT is not a 2D texture.");
257 deviceContext->setTexture(bindings->brdfLUTBinding, brdfLUTTexture->textureHandle);
261 RenderTexture * white = drawContext->renderer->getRenderResources().getRenderTexture(drawContext->context->textureManager->white);
262 deviceContext->setTexture(bindings->brdfLUTBinding, white->textureHandle);
268 SamplerState linearFiltering = {
269 SamplerState::AddressMode::Clamp,
270 SamplerState::AddressMode::Clamp,
271 SamplerState::AddressMode::Clamp,
272 SamplerState::FilterMode::MinMagMipLinear,
273 SamplerState::ComparisonFunction::Never,
279 deviceContext->setSamplerState(bindings->skySamplerBinding, drawContext->taskContext->states->getSamplerState(linearFiltering));
284 deviceContext->setSamplerState(bindings->radianceSamplerBinding, drawContext->taskContext->states->getSamplerState(linearFiltering));
287 deviceContext->setSamplerState(bindings->irradianceSamplerBinding, drawContext->taskContext->states->getSamplerState(linearFiltering));
289 if (
HandleIsValid(bindings->ambientIrradianceSamplerBinding)) {
290 deviceContext->setSamplerState(bindings->ambientIrradianceSamplerBinding, drawContext->taskContext->states->getSamplerState(SamplerState::DefaultState()));
293 SamplerState lutSamplerState = {
294 SamplerState::AddressMode::Clamp,
295 SamplerState::AddressMode::Clamp,
296 SamplerState::AddressMode::Clamp,
297 SamplerState::FilterMode::MinMagMipLinear,
298 SamplerState::ComparisonFunction::Never,
302 deviceContext->setSamplerState(bindings->brdfLUTSamplerBinding, drawContext->taskContext->states->getSamplerState(lutSamplerState));
306void Cogs::Core::updateMaterialBindings(
const DrawContext * drawContext,
const RenderMaterialInstance * renderMaterialInstance,
const EffectBinding * bindings,
bool perInstance)
308 auto deviceContext = drawContext->deviceContext;
310 auto materialInstance = renderMaterialInstance->getResource();
311 auto material = materialInstance->material;
313 for (
auto & buffer : material->constantBuffers.buffers) {
314 if (buffer.isPerInstance != perInstance)
continue;
316 auto & bufferBinding = bindings->bufferBindings[buffer.index];
319 applyMaterialProperties(drawContext, material, bufferBinding, renderMaterialInstance->buffers[buffer.index].handle);
322 applyMaterialProperties(drawContext, material, bufferBinding, bindings->buffers[buffer.index].handle);
327 for (
const TextureValue& textureProperty : materialInstance->textureVariables) {
328 if (textureProperty.property->isPerInstance) {
332 RenderTexture* renderTexture = drawContext->renderer->getRenderResources().getRenderTexture(textureProperty.texture.handle);
335 deviceContext->setTexture(textureBinding, renderTexture->textureHandle);
338 if (
HandleIsValid(textureProperty.property->texture.handle)) {
340 renderTexture = drawContext->renderer->getRenderResources().getRenderTexture(textureProperty.property->texture.handle);
347 if (
HandleIsValid(renderMaterialInstance->samplerStates[textureProperty.key])) {
348 deviceContext->setSamplerState(samplerBinding, renderMaterialInstance->samplerStates[textureProperty.key]);
357 RenderMaterial* renderMaterial = renderMaterialInstance->renderMaterial;
359 for (
size_t i = 0, N = material->textureProperties.size(); i < N; i++) {
360 const TextureProperty& textureProperty = material->textureProperties[i];
361 if (!textureProperty.isPerInstance) {
363 RenderTexture* renderTexture = drawContext->renderer->getRenderResources().getRenderTexture(textureProperty.texture.handle);
365 deviceContext->setTexture(bindings->textureBindings[textureProperty.key], renderTexture->textureHandle);
371 const RenderMaterial::TexturePropertyState& state = renderMaterial->texturePropertyStates[i];
373 deviceContext->setSamplerState(bindings->samplerBindings[textureProperty.key], state.samplerState);
384void Cogs::Core::applyMaterialPermutation(RenderTaskContext * taskContext,
const DrawContext * drawContext,
const EffectBinding * bindings,
const RenderMaterialInstance * renderMaterialInstance)
386 drawContext->deviceContext->setEffect(bindings->renderEffect->effectHandle);
387 drawContext->deviceContext->setInputLayout(bindings->renderEffect->inputHandle);
388 updateSceneBindings(taskContext, bindings);
389 updateMaterialBindings(drawContext, renderMaterialInstance, bindings,
false);
392void Cogs::Core::applyMaterialInstance(
const DrawContext * drawContext,
const EffectBinding * bindings,
const RenderMaterialInstance * renderMaterialInstance)
394 updateMaterialBindings(drawContext, renderMaterialInstance, bindings,
true);
397size_t Cogs::Core::populateObjectBuffer(
const DrawContext * drawContext,
const RenderItem* items,
size_t o,
size_t n)
399 auto deviceContext = drawContext->deviceContext;
400 auto & engineBuffers = *drawContext->engineBuffers;
401 assert(engineBuffers.objectBatch.count != 0);
403 const auto stride = engineBuffers.objectBatch.stride;
404 auto m = std::min(n - o,
size_t(engineBuffers.objectBatch.count));
406 MappedBuffer<char> objectBatch(deviceContext, engineBuffers.objectBatch.bufferHandle, MapMode::WriteDiscard);
409 for (
size_t i = 0; i < m; i++) {
410 if (items[o + i].isCustom())
continue;
411 auto * obj = (ObjectBuffer*)(objectBatch.get() + stride * i);
412 obj->worldMatrix = *items[o + i].worldMatrix;
413 obj->objectId = items[o + i].objectId;
420void Cogs::Core::applyMaterialPerObjectBatched(
const DrawContext * drawContext,
const RenderMaterialInstance * ,
const RenderItem & renderItem,
size_t o)
422 auto deviceContext = drawContext->deviceContext;
423 auto & engineBuffers = *drawContext->engineBuffers;
424 auto & batch = engineBuffers.objectBatch;
426 const auto bindings = renderItem.binding;
429 deviceContext->setConstantBuffer(bindings->objectBufferBinding,
431 batch.stride * uint32_t(o),
435 if (renderItem.poseData) {
437 deviceContext->updateBuffer(engineBuffers.animationBuffer, renderItem.poseData->transforms,
sizeof(glm::mat4) * renderItem.poseData->numPoses);
438 deviceContext->setConstantBuffer(bindings->animationBufferBinding, engineBuffers.animationBuffer);
444void Cogs::Core::applyMaterialPerObject(
const DrawContext * drawContext,
const RenderMaterialInstance * ,
const RenderItem & renderItem)
446 auto deviceContext = drawContext->deviceContext;
447 auto & engineBuffers = *drawContext->engineBuffers;
449 const auto bindings = renderItem.binding;
452 ListObjectBuffer* unifiedObjectBuffer = drawContext->listObjectBuffer;
454 if (unifiedObjectBuffer && renderItem.hasObjectBufferSlot() &&
HandleIsValid(unifiedObjectBuffer->gpu)) {
455 deviceContext->setConstantBuffer(bindings->objectBufferBinding,
456 unifiedObjectBuffer->gpu,
457 unifiedObjectBuffer->stride * renderItem.objectBufferSlot,
458 unifiedObjectBuffer->stride);
461 MappedBuffer<ObjectBuffer> objectBuffer(deviceContext, engineBuffers.objectBufferHandle, MapMode::WriteDiscard);
463 objectBuffer->worldMatrix = *renderItem.worldMatrix;
464 objectBuffer->objectId = renderItem.objectId;
466 deviceContext->setConstantBuffer(bindings->objectBufferBinding, engineBuffers.objectBufferHandle);
470 if (renderItem.poseData) {
472 deviceContext->updateBuffer(engineBuffers.animationBuffer, renderItem.poseData->transforms,
sizeof(glm::mat4) * renderItem.poseData->numPoses);
473 deviceContext->setConstantBuffer(bindings->animationBufferBinding, engineBuffers.animationBuffer);
Log implementation class.
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
static const Handle_t NoHandle
Represents a handle to nothing.