1#include "Foundation/Logging/Logger.h"
3#include "Rendering/IBindGroups.h"
4#include "Rendering/ICapabilities.h"
8#include "Systems/Core/LightSystem.h"
9#include "Systems/Core/EnvironmentSystem.h"
11#include "Resources/Mesh.h"
12#include "Resources/Skeleton.h"
13#include "Resources/Animation.h"
14#include "Resources/BasicBlueNoiseManager.h"
15#include "RenderStateUpdater.h"
16#include "RenderList.h"
18#include "Tasks/RenderTask.h"
19#include "Tasks/GenerateListTask.h"
20#include "Tasks/FilterListTask.h"
22#include "Resources/TextureManager.h"
23#include "EngineBindGroups.h"
30void Cogs::Core::updateSceneBindings(
const DrawContext * drawContext,
const CameraData * ,
const EffectBinding * bindings)
32 assert(drawContext->taskContext &&
"Invalid rendering context.");
34 updateSceneBindings(drawContext->taskContext, bindings);
37void Cogs::Core::updateSceneBindings(
const RenderTaskContext * taskContext,
const EffectBinding * bindings)
39 const EngineBuffers* engineBuffers = &taskContext->renderer->getEngineBuffers();
40 IGraphicsDevice* device = taskContext->renderer->getDevice();
41 IContext* deviceContext = device->getImmediateContext();
44 deviceContext->setConstantBuffer(bindings->sceneBufferBinding, engineBuffers->sceneBufferHandle);
47 deviceContext->setConstantBuffer(bindings->viewBufferBinding, engineBuffers->viewBufferHandle);
50 deviceContext->setSamplerState(bindings->linearSampler, taskContext->states->defaultSampler);
54 auto& blueNoiseManager = taskContext->context->blueNoiseManager;
55 blueNoiseManager->enable();
56 TextureHandle blueNoise = blueNoiseManager->getBlueNoiseHandle(
false)->texture;
57 RenderTexture * blueNoiseTexture = taskContext->renderer->getRenderResources().getRenderTexture(blueNoise);
58 if (blueNoiseTexture) {
59 deviceContext->setTexture(bindings->blueNoise, blueNoiseTexture->textureHandle);
63 auto& blueNoiseManager = taskContext->context->blueNoiseManager;
64 blueNoiseManager->enable();
65 TextureHandle blueNoise = blueNoiseManager->getBlueNoiseHandle(
true)->texture;
66 RenderTexture * blueNoiseTexture = taskContext->renderer->getRenderResources().getRenderTexture(blueNoise);
67 if (blueNoiseTexture) {
68 deviceContext->setTexture(bindings->blueNoiseStable, blueNoiseTexture->textureHandle);
73void Cogs::Core::updateEnvironmentBindings(
const DrawContext * drawContext,
const EffectBinding * bindings)
75 IContext *deviceContext = drawContext->deviceContext;
76 LightSystem *lightSystem = drawContext->context->lightSystem;
77 if (drawContext->device->getBindGroups()) {
78 EngineBindGroups& engineBindGroups = drawContext->renderer->getEngineBindGroups();
79 deviceContext->setBindGroup(engineBindGroups.lightTextures,
static_cast<uint32_t
>(BindGroup::LightTextures));
83 bool needSkyBinding =
true;
84 bool needRadianceBinding =
true;
85 bool needIrradianceBinding =
true;
86 bool needAmbientIrradianceBinding =
true;
87 bool needBrdfLUTBinding =
true;
88 bool needShadowArrayBinding =
true;
89 bool needShadowArrayBinding_1 =
true;
90 bool needShadowCubeArrayBinding =
true;
91 bool needShadowCubeArrayBinding_1 =
true;
94 deviceContext->setSamplerState(bindings->shadowSamplerBinding, drawContext->taskContext->states->shadowSampler);
98 if (!drawContext->permutation->isShadowPass()) {
100 RenderTexture * shadowTexture = drawContext->renderer->getRenderResources().getRenderTexture(lightSystem->cascadeArray);
103 deviceContext->setTexture(bindings->shadowArrayBinding, shadowTexture->textureHandle);
104 deviceContext->setSamplerState(
"", 1, drawContext->taskContext->states->shadowSampler);
105 needShadowArrayBinding =
false;
109 RenderTexture * shadowTexture = drawContext->renderer->getRenderResources().getRenderTexture(lightSystem->cascadeArray);
112 deviceContext->setTexture(bindings->shadowArrayBinding_1, shadowTexture->textureHandle);
113 deviceContext->setSamplerState(
"", 1, drawContext->taskContext->states->shadowSampler);
114 needShadowArrayBinding_1 =
false;
119 RenderTexture * shadowTexture = drawContext->renderer->getRenderResources().getRenderTexture(lightSystem->cubeArray);
122 deviceContext->setTexture(bindings->shadowCubeArrayBinding, shadowTexture->textureHandle);
123 deviceContext->setSamplerState(
"", 2, drawContext->taskContext->states->shadowSampler);
124 needShadowCubeArrayBinding =
false;
128 auto shadowTexture = drawContext->renderer->getRenderResources().getRenderTexture(lightSystem->cubeArray);
131 deviceContext->setTexture(bindings->shadowCubeArrayBinding_1, shadowTexture->textureHandle);
132 deviceContext->setSamplerState(
"", 2, drawContext->taskContext->states->shadowSampler);
133 needShadowCubeArrayBinding_1 =
false;
138 deviceContext->setSamplerState(bindings->shadowSamplerBinding, drawContext->taskContext->states->shadowSampler);
141 deviceContext->setSamplerState(bindings->shadowArraySamplerBinding, drawContext->taskContext->states->shadowSampler);
143 if (
HandleIsValid(bindings->shadowCubeArraySamplerBinding)) {
144 deviceContext->setSamplerState(bindings->shadowCubeArraySamplerBinding, drawContext->taskContext->states->shadowSampler);
149 deviceContext->setSamplerState(bindings->shadowSamplerBinding, drawContext->taskContext->states->shadowSampler);
153 auto environmentComponent = drawContext->cameraData->environment.resolveComponent<EnvironmentComponent>();
155 if (environmentComponent) {
156 if (environmentComponent->isSubmerged(drawContext->cameraData)) {
158 if (environmentComponent->subseaRadiance) {
159 RenderTexture * subseaRadianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->subseaRadiance);
160 if (subseaRadianceTexture) {
161 if (subseaRadianceTexture->description.target != ResourceDimensions::TextureCube) {
162 static int count = 0;
164 LOG_ERROR(logger,
"environment.subseaRadiance is not a cube texture.");
170 deviceContext->setTexture(bindings->skyBinding, subseaRadianceTexture->textureHandle);
171 needSkyBinding =
false;
174 deviceContext->setTexture(bindings->radianceBinding, subseaRadianceTexture->textureHandle);
175 needRadianceBinding =
false;
178 deviceContext->setTexture(bindings->irradianceBinding, subseaRadianceTexture->textureHandle);
179 needIrradianceBinding =
false;
182 deviceContext->setTexture(bindings->ambientIrradianceBinding, subseaRadianceTexture->textureHandle);
183 needAmbientIrradianceBinding =
false;
189 if (environmentComponent->skyDome &&
HandleIsValid(bindings->skyBinding)) {
191 if (RenderTexture * skyTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->skyDome); skyTexture) {
193 if (skyTexture->description.target != ResourceDimensions::TextureCube) {
194 static int warningCount = 0;
195 if (warningCount < 10) {
196 LOG_ERROR(logger,
"environment.skyDome is not a cube texture.");
201 deviceContext->setTexture(bindings->skyBinding, skyTexture->textureHandle);
202 needSkyBinding =
false;
207 if (environmentComponent->radiance &&
HandleIsValid(bindings->radianceBinding)) {
209 if (RenderTexture * radianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->radiance); radianceTexture) {
211 if (radianceTexture->description.target != ResourceDimensions::TextureCube) {
212 static int warningCount = 0;
213 if (warningCount < 10) {
214 LOG_ERROR(logger,
"environment.radiance is not a cube texture.");
219 deviceContext->setTexture(bindings->radianceBinding, radianceTexture->textureHandle);
220 needRadianceBinding =
false;
225 if (environmentComponent->irradiance &&
HandleIsValid(bindings->irradianceBinding)) {
227 if (RenderTexture * irradianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->irradiance); irradianceTexture) {
229 if (irradianceTexture->description.target != ResourceDimensions::TextureCube) {
230 static int warningCount = 0;
231 if (warningCount < 10) {
232 LOG_ERROR(logger,
"environment.irradiance is not a cube texture.");
237 deviceContext->setTexture(bindings->irradianceBinding, irradianceTexture->textureHandle);
238 needIrradianceBinding =
false;
243 if (environmentComponent->ambientIrradiance &&
HandleIsValid(bindings->ambientIrradianceBinding)) {
244 RenderTexture * ambientIrradianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->ambientIrradiance);
245 if (ambientIrradianceTexture) {
247 if (ambientIrradianceTexture->description.target != ResourceDimensions::TextureCube) {
248 static int warningCount = 0;
249 if (warningCount < 10) {
250 LOG_ERROR(logger,
"environment.ambientIrradiance is not a cube texture.");
255 deviceContext->setTexture(bindings->ambientIrradianceBinding, ambientIrradianceTexture->textureHandle);
256 needAmbientIrradianceBinding =
false;
261 if (environmentComponent->brdfLUT &&
HandleIsValid(bindings->brdfLUTBinding)) {
262 RenderTexture* brdfLUTTexture = drawContext->renderer->getRenderResources().getRenderTexture(environmentComponent->brdfLUT);
263 if (brdfLUTTexture) {
265 if (brdfLUTTexture->description.target != ResourceDimensions::Texture2D) {
266 static int warningCount = 0;
267 if (warningCount < 10) {
268 LOG_ERROR(logger,
"environment.brdfLUT is not a 2D texture.");
273 deviceContext->setTexture(bindings->brdfLUTBinding, brdfLUTTexture->textureHandle);
274 needBrdfLUTBinding =
false;
278 RenderTexture * white = drawContext->renderer->getRenderResources().getRenderTexture(drawContext->context->textureManager->white);
279 deviceContext->setTexture(bindings->brdfLUTBinding, white->textureHandle);
280 needBrdfLUTBinding =
false;
286 if (drawContext->device->getType() == GraphicsDeviceType::WebGPU){
291 TextureHandle whiteCube = drawContext->context->textureManager->whiteCube;
292 RenderTexture* skyTexture = drawContext->renderer->getRenderResources().getRenderTexture(whiteCube);
294 LOG_INFO_ONCE(logger,
"Setting dummy environment.skyDome.");
295 deviceContext->setTexture(bindings->skyBinding, skyTexture->textureHandle);
300 if(
HandleIsValid(bindings->radianceBinding) && needRadianceBinding) {
301 TextureHandle whiteCube = drawContext->context->textureManager->whiteCube;
302 RenderTexture* radianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(whiteCube);
303 if (radianceTexture) {
304 LOG_INFO_ONCE(logger,
"Setting dummy environment.radiance.");
305 deviceContext->setTexture(bindings->radianceBinding, radianceTexture->textureHandle);
310 if(
HandleIsValid(bindings->irradianceBinding) && needIrradianceBinding) {
311 TextureHandle whiteCube = drawContext->context->textureManager->whiteCube;
312 RenderTexture* irradianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(whiteCube);
313 if (irradianceTexture) {
314 LOG_INFO_ONCE(logger,
"Setting dummy environment.irradiance.");
315 deviceContext->setTexture(bindings->irradianceBinding, irradianceTexture->textureHandle);
320 if(
HandleIsValid(bindings->ambientIrradianceBinding) && needAmbientIrradianceBinding) {
321 TextureHandle whiteCube = drawContext->context->textureManager->whiteCube;
322 RenderTexture* ambientIrradianceTexture = drawContext->renderer->getRenderResources().getRenderTexture(whiteCube);
323 if (ambientIrradianceTexture) {
324 LOG_INFO_ONCE(logger,
"Setting dummy environment.ambientIrradiance.");
325 deviceContext->setTexture(bindings->ambientIrradianceBinding, ambientIrradianceTexture->textureHandle);
330 if(
HandleIsValid(bindings->brdfLUTBinding) && needBrdfLUTBinding) {
331 RenderTexture* white = drawContext->renderer->getRenderResources().getRenderTexture(drawContext->context->textureManager->white);
333 LOG_INFO_ONCE(logger,
"Setting dummy environment.brdfLUT.");
334 deviceContext->setTexture(bindings->brdfLUTBinding, white->textureHandle);
339 if(
HandleIsValid(bindings->shadowArrayBinding) && needShadowArrayBinding) {
340 RenderTexture* dummy = drawContext->renderer->getRenderResources().getRenderTexture(drawContext->context->textureManager->whiteDepthArray);
342 LOG_INFO_ONCE(logger,
"Setting dummy cascadedShadowMap.");
343 deviceContext->setTexture(bindings->shadowArrayBinding, dummy->textureHandle);
346 if(
HandleIsValid(bindings->shadowArrayBinding_1) && needShadowArrayBinding_1) {
347 RenderTexture* dummy = drawContext->renderer->getRenderResources().getRenderTexture(drawContext->context->textureManager->whiteDepthArray);
349 deviceContext->setTexture(bindings->shadowArrayBinding_1, dummy->textureHandle);
354 if(
HandleIsValid(bindings->shadowCubeArrayBinding) && needShadowCubeArrayBinding) {
355 RenderTexture* dummy = drawContext->renderer->getRenderResources().getRenderTexture(drawContext->context->textureManager->whiteDepthCube);
357 LOG_INFO_ONCE(logger,
"Setting dummy cubeShadowMap.");
358 deviceContext->setTexture(bindings->shadowCubeArrayBinding, dummy->textureHandle);
361 if(
HandleIsValid(bindings->shadowCubeArrayBinding_1) && needShadowCubeArrayBinding_1) {
362 RenderTexture* dummy = drawContext->renderer->getRenderResources().getRenderTexture(drawContext->context->textureManager->whiteDepthCube);
364 deviceContext->setTexture(bindings->shadowCubeArrayBinding_1, dummy->textureHandle);
369 SamplerState linearFiltering = {
370 SamplerState::AddressMode::Clamp,
371 SamplerState::AddressMode::Clamp,
372 SamplerState::AddressMode::Clamp,
373 SamplerState::FilterMode::MinMagMipLinear,
374 SamplerState::ComparisonFunction::Never,
380 deviceContext->setSamplerState(bindings->skySamplerBinding, drawContext->taskContext->states->getSamplerState(linearFiltering));
385 deviceContext->setSamplerState(bindings->radianceSamplerBinding, drawContext->taskContext->states->getSamplerState(linearFiltering));
388 deviceContext->setSamplerState(bindings->irradianceSamplerBinding, drawContext->taskContext->states->getSamplerState(linearFiltering));
390 if (
HandleIsValid(bindings->ambientIrradianceSamplerBinding)) {
391 deviceContext->setSamplerState(bindings->ambientIrradianceSamplerBinding, drawContext->taskContext->states->getSamplerState(SamplerState::DefaultState()));
394 SamplerState lutSamplerState = {
395 SamplerState::AddressMode::Clamp,
396 SamplerState::AddressMode::Clamp,
397 SamplerState::AddressMode::Clamp,
398 SamplerState::FilterMode::MinMagMipLinear,
399 SamplerState::ComparisonFunction::Never,
403 deviceContext->setSamplerState(bindings->brdfLUTSamplerBinding, drawContext->taskContext->states->getSamplerState(lutSamplerState));
407void Cogs::Core::updateMaterialBindings(
const DrawContext * drawContext,
const RenderMaterialInstance * renderMaterialInstance,
const EffectBinding * bindings,
bool perInstance)
409 auto deviceContext = drawContext->deviceContext;
411 auto materialInstance = renderMaterialInstance->getResource();
412 auto material = materialInstance->material;
414 for (
auto & buffer : material->constantBuffers.buffers) {
415 if (buffer.isPerInstance != perInstance)
continue;
417 auto & bufferBinding = bindings->bufferBindings[buffer.index];
421 deviceContext->setConstantBuffer(bufferBinding, renderMaterialInstance->buffers[buffer.index].handle);
426 deviceContext->setConstantBuffer(bufferBinding, bindings->buffers[buffer.index].handle);
432 for (
const TextureValue& textureProperty : materialInstance->textureVariables) {
433 if (textureProperty.property->isPerInstance) {
437 RenderTexture* renderTexture = drawContext->renderer->getRenderResources().getRenderTexture(textureProperty.texture.handle);
440 deviceContext->setTexture(textureBinding, renderTexture->textureHandle);
443 if (
HandleIsValid(textureProperty.property->texture.handle)) {
445 renderTexture = drawContext->renderer->getRenderResources().getRenderTexture(textureProperty.property->texture.handle);
452 if (
HandleIsValid(renderMaterialInstance->samplerStates[textureProperty.key])) {
453 deviceContext->setSamplerState(samplerBinding, renderMaterialInstance->samplerStates[textureProperty.key]);
462 RenderMaterial* renderMaterial = renderMaterialInstance->renderMaterial;
464 for (
size_t i = 0, N = material->textureProperties.size(); i < N; i++) {
465 const TextureProperty& textureProperty = material->textureProperties[i];
466 if (!textureProperty.isPerInstance) {
468 RenderTexture* renderTexture = drawContext->renderer->getRenderResources().getRenderTexture(textureProperty.texture.handle);
470 deviceContext->setTexture(bindings->textureBindings[textureProperty.key], renderTexture->textureHandle);
476 const RenderMaterial::TexturePropertyState& state = renderMaterial->texturePropertyStates[i];
478 deviceContext->setSamplerState(bindings->samplerBindings[textureProperty.key], state.samplerState);
489void Cogs::Core::applyMaterialPermutation(RenderTaskContext * taskContext,
const DrawContext * drawContext,
const EffectBinding * bindings,
const RenderMaterialInstance * renderMaterialInstance)
491 drawContext->deviceContext->setEffect(bindings->renderEffect->effectHandle);
492 drawContext->deviceContext->setInputLayout(bindings->renderEffect->inputHandle);
493 updateSceneBindings(taskContext, bindings);
494 updateMaterialBindings(drawContext, renderMaterialInstance, bindings,
false);
497void Cogs::Core::applyMaterialInstance(
const DrawContext * drawContext,
const EffectBinding * bindings,
const RenderMaterialInstance * renderMaterialInstance)
499 updateMaterialBindings(drawContext, renderMaterialInstance, bindings,
true);
502size_t Cogs::Core::populateObjectBuffer(
const DrawContext * drawContext,
const RenderItem* items,
size_t o,
size_t n)
504 auto deviceContext = drawContext->deviceContext;
505 auto & engineBuffers = *drawContext->engineBuffers;
506 assert(engineBuffers.objectBatch.count != 0);
508 const auto stride = engineBuffers.objectBatch.stride;
509 auto m = std::min(n - o,
size_t(engineBuffers.objectBatch.count));
511 MappedBuffer<char> objectBatch(deviceContext, engineBuffers.objectBatch.bufferHandle, MapMode::WriteDiscard);
514 for (
size_t i = 0; i < m; i++) {
515 if (items[o + i].isCustom())
continue;
516 auto * obj = (ObjectBuffer*)(objectBatch.get() + stride * i);
517 obj->encodeWorldMatrix(*items[o + i].worldMatrix);
518 obj->encodeObjectId(items[o + i].objectId);
525void Cogs::Core::applyMaterialPerObjectBatched(
const DrawContext * drawContext,
const RenderMaterialInstance * ,
const RenderItem & renderItem,
size_t o,
const EffectBinding * binding)
527 auto deviceContext = drawContext->deviceContext;
528 auto & engineBuffers = *drawContext->engineBuffers;
529 auto & batch = engineBuffers.objectBatch;
531 const auto bindings = binding;
534 deviceContext->setConstantBuffer(bindings->objectBufferBinding,
536 batch.stride * uint32_t(o),
540 if (renderItem.poseData) {
542 deviceContext->updateBuffer(engineBuffers.animationBuffer, renderItem.poseData->transforms,
sizeof(glm::mat4) * renderItem.poseData->numPoses);
543 deviceContext->setConstantBuffer(bindings->animationBufferBinding, engineBuffers.animationBuffer);
549void Cogs::Core::applyMaterialPerObject(
const DrawContext * drawContext,
const RenderMaterialInstance * ,
const RenderItem & renderItem,
const EffectBinding * binding)
551 auto deviceContext = drawContext->deviceContext;
552 auto & engineBuffers = *drawContext->engineBuffers;
554 const auto bindings = binding;
557 ArrayObjectBuffer* arrayObjectBuffer = drawContext->arrayObjectBuffer;
558 ListObjectBuffer* listObjectBuffer = drawContext->listObjectBuffer;
560 if (arrayObjectBuffer && renderItem.hasObjectArrayBufferSlot() &&
HandleIsValid(arrayObjectBuffer->gpu)){
561 uint32_t bind_offset = renderItem.objectArrayBufferSlot / ArrayObjectBuffer::arrayGranularity;
562 deviceContext->setConstantBuffer(bindings->objectBufferBinding,
563 arrayObjectBuffer->gpu,
564 ArrayObjectBuffer::bindSize*bind_offset,
565 ArrayObjectBuffer::bindSize);
567 else if (listObjectBuffer && renderItem.hasObjectBufferSlot() &&
HandleIsValid(listObjectBuffer->gpu)) {
568 deviceContext->setConstantBuffer(bindings->objectBufferBinding,
569 listObjectBuffer->gpu,
570 listObjectBuffer->stride * renderItem.objectBufferSlot,
571 listObjectBuffer->stride);
574 MappedBuffer<ObjectBuffer> objectBuffer(deviceContext, engineBuffers.objectBufferHandle, MapMode::WriteDiscard);
576 objectBuffer->encodeWorldMatrix(*renderItem.worldMatrix);
577 objectBuffer->encodeObjectId(renderItem.objectId);
579 deviceContext->setConstantBuffer(bindings->objectBufferBinding, engineBuffers.objectBufferHandle);
583 if (renderItem.poseData) {
585 deviceContext->updateBuffer(engineBuffers.animationBuffer, renderItem.poseData->transforms,
sizeof(glm::mat4) * renderItem.poseData->numPoses);
586 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.