rendering: add builtin alpha-test pass support
This commit is contained in:
@@ -11,7 +11,9 @@
|
||||
#include "Rendering/RenderSurface.h"
|
||||
#include "Resources/Material/Material.h"
|
||||
#include "Resources/Mesh/Mesh.h"
|
||||
#include "Resources/Texture/Texture.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
@@ -37,6 +39,40 @@ bool IsSupportedPerObjectOnlyBindingPlan(const BuiltinPassResourceBindingPlan& b
|
||||
!bindingPlan.usesSamplers;
|
||||
}
|
||||
|
||||
bool UsesContiguousDescriptorSets(const BuiltinPassResourceBindingPlan& bindingPlan) {
|
||||
if (bindingPlan.bindings.Empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<bool> usedSets(static_cast<size_t>(bindingPlan.maxSetIndex) + 1u, false);
|
||||
Core::uint32 minSet = UINT32_MAX;
|
||||
Core::uint32 maxSet = 0;
|
||||
for (const BuiltinPassResourceBindingDesc& binding : bindingPlan.bindings) {
|
||||
usedSets[binding.location.set] = true;
|
||||
minSet = std::min(minSet, binding.location.set);
|
||||
maxSet = std::max(maxSet, binding.location.set);
|
||||
}
|
||||
|
||||
for (Core::uint32 setIndex = minSet; setIndex <= maxSet; ++setIndex) {
|
||||
if (!usedSets[setIndex]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsSupportedAlphaTestBindingPlan(const BuiltinPassResourceBindingPlan& bindingPlan) {
|
||||
return bindingPlan.perObject.IsValid() &&
|
||||
bindingPlan.material.IsValid() &&
|
||||
bindingPlan.baseColorTexture.IsValid() &&
|
||||
bindingPlan.linearClampSampler.IsValid() &&
|
||||
!bindingPlan.lighting.IsValid() &&
|
||||
!bindingPlan.shadowReceiver.IsValid() &&
|
||||
!bindingPlan.shadowMapTexture.IsValid() &&
|
||||
!bindingPlan.shadowMapSampler.IsValid();
|
||||
}
|
||||
|
||||
uint32_t ResolveSurfaceColorAttachmentCount(const RenderSurface& surface) {
|
||||
const std::vector<RHI::RHIResourceView*>& colorAttachments = surface.GetColorAttachments();
|
||||
return (!colorAttachments.empty() && colorAttachments[0] != nullptr) ? 1u : 0u;
|
||||
@@ -131,16 +167,66 @@ bool BuiltinDepthStylePassBase::CreateResources(const RenderContext& context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::SamplerDesc samplerDesc = {};
|
||||
samplerDesc.filter = static_cast<uint32_t>(RHI::FilterMode::Linear);
|
||||
samplerDesc.addressU = static_cast<uint32_t>(RHI::TextureAddressMode::Clamp);
|
||||
samplerDesc.addressV = static_cast<uint32_t>(RHI::TextureAddressMode::Clamp);
|
||||
samplerDesc.addressW = static_cast<uint32_t>(RHI::TextureAddressMode::Clamp);
|
||||
samplerDesc.mipLodBias = 0.0f;
|
||||
samplerDesc.maxAnisotropy = 1;
|
||||
samplerDesc.comparisonFunc = static_cast<uint32_t>(RHI::ComparisonFunc::Always);
|
||||
samplerDesc.minLod = 0.0f;
|
||||
samplerDesc.maxLod = 1000.0f;
|
||||
m_sampler = context.device->CreateSampler(samplerDesc);
|
||||
if (m_sampler == nullptr) {
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned char whitePixels2D[4] = {
|
||||
255, 255, 255, 255
|
||||
};
|
||||
RHI::TextureDesc fallback2DDesc = {};
|
||||
fallback2DDesc.width = 1;
|
||||
fallback2DDesc.height = 1;
|
||||
fallback2DDesc.depth = 1;
|
||||
fallback2DDesc.mipLevels = 1;
|
||||
fallback2DDesc.arraySize = 1;
|
||||
fallback2DDesc.format = static_cast<uint32_t>(RHI::Format::R8G8B8A8_UNorm);
|
||||
fallback2DDesc.textureType = static_cast<uint32_t>(RHI::TextureType::Texture2D);
|
||||
fallback2DDesc.sampleCount = 1;
|
||||
fallback2DDesc.sampleQuality = 0;
|
||||
fallback2DDesc.flags = 0;
|
||||
m_fallbackTexture2D = context.device->CreateTexture(
|
||||
fallback2DDesc,
|
||||
whitePixels2D,
|
||||
sizeof(whitePixels2D),
|
||||
sizeof(whitePixels2D));
|
||||
if (m_fallbackTexture2D == nullptr) {
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc fallback2DViewDesc = {};
|
||||
fallback2DViewDesc.format = static_cast<uint32_t>(RHI::Format::R8G8B8A8_UNorm);
|
||||
fallback2DViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
|
||||
fallback2DViewDesc.mipLevel = 0;
|
||||
m_fallbackTexture2DView = context.device->CreateShaderResourceView(m_fallbackTexture2D, fallback2DViewDesc);
|
||||
if (m_fallbackTexture2DView == nullptr) {
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BuiltinDepthStylePassBase::DestroyResources() {
|
||||
m_resourceCache.Shutdown();
|
||||
|
||||
for (auto& descriptorSetEntry : m_perObjectSets) {
|
||||
DestroyOwnedDescriptorSet(descriptorSetEntry.second);
|
||||
for (auto& descriptorSetEntry : m_dynamicDescriptorSets) {
|
||||
DestroyOwnedDescriptorSet(descriptorSetEntry.second.descriptorSet);
|
||||
}
|
||||
m_perObjectSets.clear();
|
||||
m_dynamicDescriptorSets.clear();
|
||||
|
||||
for (auto& pipelineEntry : m_pipelineStates) {
|
||||
if (pipelineEntry.second != nullptr) {
|
||||
@@ -155,6 +241,24 @@ void BuiltinDepthStylePassBase::DestroyResources() {
|
||||
}
|
||||
m_passResourceLayouts.clear();
|
||||
|
||||
if (m_fallbackTexture2DView != nullptr) {
|
||||
m_fallbackTexture2DView->Shutdown();
|
||||
delete m_fallbackTexture2DView;
|
||||
m_fallbackTexture2DView = nullptr;
|
||||
}
|
||||
|
||||
if (m_fallbackTexture2D != nullptr) {
|
||||
m_fallbackTexture2D->Shutdown();
|
||||
delete m_fallbackTexture2D;
|
||||
m_fallbackTexture2D = nullptr;
|
||||
}
|
||||
|
||||
if (m_sampler != nullptr) {
|
||||
m_sampler->Shutdown();
|
||||
delete m_sampler;
|
||||
m_sampler = nullptr;
|
||||
}
|
||||
|
||||
m_device = nullptr;
|
||||
m_backendType = RHI::RHIType::D3D12;
|
||||
m_builtinShader.Reset();
|
||||
@@ -235,7 +339,7 @@ BuiltinDepthStylePassBase::ResolvedShaderPass BuiltinDepthStylePassBase::Resolve
|
||||
}
|
||||
|
||||
if (m_builtinShader.IsValid() &&
|
||||
tryResolveFromShader(m_builtinShader.Get(), nullptr)) {
|
||||
tryResolveFromShader(m_builtinShader.Get(), material)) {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
@@ -259,9 +363,19 @@ bool BuiltinDepthStylePassBase::TryBuildSupportedBindingPlan(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsSupportedPerObjectOnlyBindingPlan(outPlan)) {
|
||||
if (!UsesContiguousDescriptorSets(outPlan)) {
|
||||
if (outError != nullptr) {
|
||||
*outError = "Builtin depth-style pass currently requires exactly one PerObject constant-buffer binding";
|
||||
*outError = "Builtin depth-style pass requires contiguous descriptor set indices";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsSupportedPerObjectOnlyBindingPlan(outPlan) &&
|
||||
!IsSupportedAlphaTestBindingPlan(outPlan)) {
|
||||
if (outError != nullptr) {
|
||||
*outError =
|
||||
"Builtin depth-style pass requires either PerObject-only bindings or the alpha-test contract "
|
||||
"(PerObject + Material + BaseColorTexture + LinearClampSampler)";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -304,24 +418,26 @@ BuiltinDepthStylePassBase::PassResourceLayout* BuiltinDepthStylePassBase::GetOrC
|
||||
return failLayout(contextualError.CStr());
|
||||
}
|
||||
|
||||
std::vector<BuiltinPassSetLayoutMetadata> setLayouts;
|
||||
Containers::String setLayoutError;
|
||||
if (!TryBuildBuiltinPassSetLayouts(bindingPlan, setLayouts, &setLayoutError)) {
|
||||
if (!TryBuildBuiltinPassSetLayouts(bindingPlan, passLayout.setLayouts, &setLayoutError)) {
|
||||
return failLayout(setLayoutError.CStr());
|
||||
}
|
||||
|
||||
if (bindingPlan.perObject.set >= setLayouts.size()) {
|
||||
if (bindingPlan.perObject.set >= passLayout.setLayouts.size()) {
|
||||
return failLayout("Builtin depth-style pass produced an invalid PerObject descriptor set index");
|
||||
}
|
||||
|
||||
passLayout.perObject = bindingPlan.perObject;
|
||||
passLayout.firstDescriptorSet = bindingPlan.firstDescriptorSet;
|
||||
passLayout.perObjectSetLayout = setLayouts[bindingPlan.perObject.set];
|
||||
RefreshBuiltinPassSetLayoutMetadata(passLayout.perObjectSetLayout);
|
||||
passLayout.descriptorSetCount = bindingPlan.descriptorSetCount;
|
||||
passLayout.staticDescriptorSets.resize(passLayout.setLayouts.size());
|
||||
passLayout.perObject = bindingPlan.perObject;
|
||||
passLayout.material = bindingPlan.material;
|
||||
passLayout.baseColorTexture = bindingPlan.baseColorTexture;
|
||||
passLayout.linearClampSampler = bindingPlan.linearClampSampler;
|
||||
|
||||
std::vector<RHI::DescriptorSetLayoutDesc> nativeSetLayouts(setLayouts.size());
|
||||
for (size_t setIndex = 0; setIndex < setLayouts.size(); ++setIndex) {
|
||||
nativeSetLayouts[setIndex] = setLayouts[setIndex].layout;
|
||||
std::vector<RHI::DescriptorSetLayoutDesc> nativeSetLayouts(passLayout.setLayouts.size());
|
||||
for (size_t setIndex = 0; setIndex < passLayout.setLayouts.size(); ++setIndex) {
|
||||
nativeSetLayouts[setIndex] = passLayout.setLayouts[setIndex].layout;
|
||||
}
|
||||
|
||||
RHI::RHIPipelineLayoutDesc pipelineLayoutDesc = {};
|
||||
@@ -333,7 +449,7 @@ BuiltinDepthStylePassBase::PassResourceLayout* BuiltinDepthStylePassBase::GetOrC
|
||||
}
|
||||
|
||||
const auto result = m_passResourceLayouts.emplace(passLayoutKey, std::move(passLayout));
|
||||
RefreshBuiltinPassSetLayoutMetadata(result.first->second.perObjectSetLayout);
|
||||
RefreshBuiltinPassSetLayouts(result.first->second.setLayouts);
|
||||
return &result.first->second;
|
||||
}
|
||||
|
||||
@@ -412,31 +528,98 @@ bool BuiltinDepthStylePassBase::CreateOwnedDescriptorSet(
|
||||
return true;
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* BuiltinDepthStylePassBase::GetOrCreatePerObjectSet(
|
||||
RHI::RHIDescriptorSet* BuiltinDepthStylePassBase::GetOrCreateStaticDescriptorSet(
|
||||
const PassLayoutKey& passLayoutKey,
|
||||
PassResourceLayout& passLayout,
|
||||
Core::uint32 setIndex) {
|
||||
(void)passLayoutKey;
|
||||
|
||||
if (setIndex >= passLayout.setLayouts.size() ||
|
||||
setIndex >= passLayout.staticDescriptorSets.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const BuiltinPassSetLayoutMetadata& setLayout = passLayout.setLayouts[setIndex];
|
||||
if (setLayout.layout.bindingCount == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OwnedDescriptorSet& descriptorSet = passLayout.staticDescriptorSets[setIndex];
|
||||
if (descriptorSet.set == nullptr) {
|
||||
if (!CreateOwnedDescriptorSet(setLayout, descriptorSet)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (setLayout.usesLinearClampSampler) {
|
||||
if (!passLayout.linearClampSampler.IsValid() ||
|
||||
passLayout.linearClampSampler.set != setIndex ||
|
||||
m_sampler == nullptr) {
|
||||
DestroyOwnedDescriptorSet(descriptorSet);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
descriptorSet.set->UpdateSampler(passLayout.linearClampSampler.binding, m_sampler);
|
||||
}
|
||||
}
|
||||
|
||||
return descriptorSet.set;
|
||||
}
|
||||
|
||||
BuiltinDepthStylePassBase::CachedDescriptorSet* BuiltinDepthStylePassBase::GetOrCreateDynamicDescriptorSet(
|
||||
const PassLayoutKey& passLayoutKey,
|
||||
const PassResourceLayout& passLayout,
|
||||
Core::uint64 objectId) {
|
||||
if (!passLayout.perObject.IsValid() ||
|
||||
passLayout.perObjectSetLayout.layout.bindingCount == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PerObjectSetKey key = {};
|
||||
const BuiltinPassSetLayoutMetadata& setLayout,
|
||||
Core::uint32 setIndex,
|
||||
Core::uint64 objectId,
|
||||
const Resources::Material* material,
|
||||
const MaterialConstantPayloadView& materialConstants,
|
||||
RHI::RHIResourceView* baseColorTextureView) {
|
||||
DynamicDescriptorSetKey key = {};
|
||||
key.passLayout = passLayoutKey;
|
||||
key.setIndex = setIndex;
|
||||
key.objectId = objectId;
|
||||
key.material = material;
|
||||
|
||||
const auto existing = m_perObjectSets.find(key);
|
||||
if (existing != m_perObjectSets.end()) {
|
||||
return existing->second.set;
|
||||
CachedDescriptorSet& cachedDescriptorSet = m_dynamicDescriptorSets[key];
|
||||
if (cachedDescriptorSet.descriptorSet.set == nullptr) {
|
||||
if (!CreateOwnedDescriptorSet(setLayout, cachedDescriptorSet.descriptorSet)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
OwnedDescriptorSet descriptorSet = {};
|
||||
if (!CreateOwnedDescriptorSet(passLayout.perObjectSetLayout, descriptorSet)) {
|
||||
return nullptr;
|
||||
const Core::uint64 materialVersion = material != nullptr ? material->GetChangeVersion() : 0;
|
||||
if (setLayout.usesMaterial) {
|
||||
if (!passLayout.material.IsValid() ||
|
||||
passLayout.material.set != setIndex ||
|
||||
!materialConstants.IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (cachedDescriptorSet.materialVersion != materialVersion) {
|
||||
cachedDescriptorSet.descriptorSet.set->WriteConstant(
|
||||
passLayout.material.binding,
|
||||
materialConstants.data,
|
||||
materialConstants.size);
|
||||
}
|
||||
}
|
||||
|
||||
const auto result = m_perObjectSets.emplace(key, descriptorSet);
|
||||
return result.first->second.set;
|
||||
if (setLayout.usesBaseColorTexture) {
|
||||
if (baseColorTextureView == nullptr ||
|
||||
!passLayout.baseColorTexture.IsValid() ||
|
||||
passLayout.baseColorTexture.set != setIndex) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (cachedDescriptorSet.baseColorTextureView != baseColorTextureView) {
|
||||
cachedDescriptorSet.descriptorSet.set->Update(
|
||||
passLayout.baseColorTexture.binding,
|
||||
baseColorTextureView);
|
||||
}
|
||||
}
|
||||
|
||||
cachedDescriptorSet.materialVersion = materialVersion;
|
||||
cachedDescriptorSet.baseColorTextureView = baseColorTextureView;
|
||||
return &cachedDescriptorSet;
|
||||
}
|
||||
|
||||
void BuiltinDepthStylePassBase::DestroyOwnedDescriptorSet(OwnedDescriptorSet& descriptorSet) {
|
||||
@@ -454,15 +637,46 @@ void BuiltinDepthStylePassBase::DestroyOwnedDescriptorSet(OwnedDescriptorSet& de
|
||||
}
|
||||
|
||||
void BuiltinDepthStylePassBase::DestroyPassResourceLayout(PassResourceLayout& passLayout) {
|
||||
for (OwnedDescriptorSet& descriptorSet : passLayout.staticDescriptorSets) {
|
||||
DestroyOwnedDescriptorSet(descriptorSet);
|
||||
}
|
||||
passLayout.staticDescriptorSets.clear();
|
||||
|
||||
if (passLayout.pipelineLayout != nullptr) {
|
||||
passLayout.pipelineLayout->Shutdown();
|
||||
delete passLayout.pipelineLayout;
|
||||
passLayout.pipelineLayout = nullptr;
|
||||
}
|
||||
|
||||
passLayout.setLayouts.clear();
|
||||
passLayout.perObject = {};
|
||||
passLayout.perObjectSetLayout = {};
|
||||
passLayout.material = {};
|
||||
passLayout.baseColorTexture = {};
|
||||
passLayout.linearClampSampler = {};
|
||||
passLayout.firstDescriptorSet = 0;
|
||||
passLayout.descriptorSetCount = 0;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* BuiltinDepthStylePassBase::ResolveTextureView(
|
||||
const Resources::Texture* texture) {
|
||||
if (texture == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const RenderResourceCache::CachedTexture* cachedTexture = m_resourceCache.GetOrCreateTexture(m_device, texture);
|
||||
if (cachedTexture != nullptr && cachedTexture->shaderResourceView != nullptr) {
|
||||
return cachedTexture->shaderResourceView;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* BuiltinDepthStylePassBase::ResolveTextureView(
|
||||
const VisibleRenderItem& visibleItem) {
|
||||
const Resources::Material* material = ResolveMaterial(visibleItem);
|
||||
const Resources::Texture* texture = ResolveBuiltinBaseColorTexture(material);
|
||||
RHI::RHIResourceView* textureView = ResolveTextureView(texture);
|
||||
return textureView != nullptr ? textureView : m_fallbackTexture2DView;
|
||||
}
|
||||
|
||||
bool BuiltinDepthStylePassBase::DrawVisibleItem(
|
||||
@@ -531,18 +745,6 @@ bool BuiltinDepthStylePassBase::DrawVisibleItem(
|
||||
commandList->SetIndexBuffer(cachedMesh->indexBufferView, 0);
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* constantSet = GetOrCreatePerObjectSet(
|
||||
passLayoutKey,
|
||||
*passLayout,
|
||||
visibleItem.gameObject->GetID());
|
||||
if (constantSet == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String("BuiltinDepthStylePassBase failed to allocate descriptor set for ") +
|
||||
visibleItem.gameObject->GetName().c_str()).CStr());
|
||||
return false;
|
||||
}
|
||||
|
||||
const Math::Matrix4x4 projectionMatrix =
|
||||
m_passType == BuiltinMaterialPass::ShadowCaster
|
||||
? sceneData.cameraData.viewProjection
|
||||
@@ -556,14 +758,122 @@ bool BuiltinDepthStylePassBase::DrawVisibleItem(
|
||||
viewMatrix,
|
||||
visibleItem.localToWorld.Transpose()
|
||||
};
|
||||
constantSet->WriteConstant(passLayout->perObject.binding, &constants, sizeof(constants));
|
||||
|
||||
RHI::RHIDescriptorSet* descriptorSets[] = { constantSet };
|
||||
commandList->SetGraphicsDescriptorSets(
|
||||
passLayout->firstDescriptorSet,
|
||||
1,
|
||||
descriptorSets,
|
||||
passLayout->pipelineLayout);
|
||||
MaterialConstantPayloadView materialConstants = ResolveSchemaMaterialConstantPayload(material);
|
||||
FallbackPerMaterialConstants fallbackMaterialConstants = {};
|
||||
if (!materialConstants.IsValid()) {
|
||||
const BuiltinForwardMaterialData materialData = BuildBuiltinForwardMaterialData(material);
|
||||
fallbackMaterialConstants.baseColorFactor = materialData.baseColorFactor;
|
||||
fallbackMaterialConstants.alphaCutoffParams = Math::Vector4(
|
||||
materialData.alphaCutoff,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f);
|
||||
static const Resources::MaterialConstantFieldDesc kFallbackMaterialConstantFields[] = {
|
||||
{
|
||||
Containers::String("_BaseColor"),
|
||||
Resources::MaterialPropertyType::Float4,
|
||||
0,
|
||||
sizeof(Math::Vector4),
|
||||
sizeof(Math::Vector4)
|
||||
},
|
||||
{
|
||||
Containers::String("_Cutoff"),
|
||||
Resources::MaterialPropertyType::Float,
|
||||
sizeof(Math::Vector4),
|
||||
sizeof(float),
|
||||
sizeof(Math::Vector4)
|
||||
}
|
||||
};
|
||||
materialConstants.data = &fallbackMaterialConstants;
|
||||
materialConstants.size = sizeof(fallbackMaterialConstants);
|
||||
materialConstants.layout = {
|
||||
kFallbackMaterialConstantFields,
|
||||
2,
|
||||
sizeof(fallbackMaterialConstants)
|
||||
};
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* baseColorTextureView = ResolveTextureView(visibleItem);
|
||||
if (passLayout->baseColorTexture.IsValid() && baseColorTextureView == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String("BuiltinDepthStylePassBase failed to resolve base color texture for ") +
|
||||
visibleItem.gameObject->GetName().c_str()).CStr());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (passLayout->descriptorSetCount > 0) {
|
||||
std::vector<RHI::RHIDescriptorSet*> descriptorSets(passLayout->descriptorSetCount, nullptr);
|
||||
|
||||
for (Core::uint32 descriptorOffset = 0; descriptorOffset < passLayout->descriptorSetCount; ++descriptorOffset) {
|
||||
const Core::uint32 setIndex = passLayout->firstDescriptorSet + descriptorOffset;
|
||||
if (setIndex >= passLayout->setLayouts.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const BuiltinPassSetLayoutMetadata& setLayout = passLayout->setLayouts[setIndex];
|
||||
if (setLayout.layout.bindingCount == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* descriptorSet = nullptr;
|
||||
if (setLayout.usesPerObject ||
|
||||
setLayout.usesMaterial ||
|
||||
setLayout.usesBaseColorTexture) {
|
||||
const Core::uint64 objectId =
|
||||
setLayout.usesPerObject ? visibleItem.gameObject->GetID() : 0;
|
||||
const Resources::Material* materialKey =
|
||||
(setLayout.usesMaterial || setLayout.usesBaseColorTexture) ? material : nullptr;
|
||||
|
||||
CachedDescriptorSet* cachedDescriptorSet = GetOrCreateDynamicDescriptorSet(
|
||||
passLayoutKey,
|
||||
*passLayout,
|
||||
setLayout,
|
||||
setIndex,
|
||||
objectId,
|
||||
materialKey,
|
||||
materialConstants,
|
||||
baseColorTextureView);
|
||||
if (cachedDescriptorSet == nullptr || cachedDescriptorSet->descriptorSet.set == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String("BuiltinDepthStylePassBase failed to allocate dynamic descriptor set for ") +
|
||||
visibleItem.gameObject->GetName().c_str()).CStr());
|
||||
return false;
|
||||
}
|
||||
|
||||
descriptorSet = cachedDescriptorSet->descriptorSet.set;
|
||||
if (setLayout.usesPerObject) {
|
||||
if (!passLayout->perObject.IsValid() || passLayout->perObject.set != setIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
descriptorSet->WriteConstant(
|
||||
passLayout->perObject.binding,
|
||||
&constants,
|
||||
sizeof(constants));
|
||||
}
|
||||
} else {
|
||||
descriptorSet = GetOrCreateStaticDescriptorSet(passLayoutKey, *passLayout, setIndex);
|
||||
if (descriptorSet == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String("BuiltinDepthStylePassBase failed to allocate static descriptor set for ") +
|
||||
visibleItem.gameObject->GetName().c_str()).CStr());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
descriptorSets[descriptorOffset] = descriptorSet;
|
||||
}
|
||||
|
||||
commandList->SetGraphicsDescriptorSets(
|
||||
passLayout->firstDescriptorSet,
|
||||
passLayout->descriptorSetCount,
|
||||
descriptorSets.data(),
|
||||
passLayout->pipelineLayout);
|
||||
}
|
||||
|
||||
if (visibleItem.hasSection) {
|
||||
const Containers::Array<Resources::MeshSection>& sections = visibleItem.mesh->GetSections();
|
||||
|
||||
@@ -183,7 +183,7 @@ BuiltinForwardPipeline::ResolvedShaderPass BuiltinForwardPipeline::ResolveSurfac
|
||||
if (builtinShaderHandle->IsValid()) {
|
||||
const Resources::Shader* builtinShader = builtinShaderHandle->Get();
|
||||
if (const Resources::ShaderPass* shaderPass =
|
||||
FindCompatibleSurfacePass(*builtinShader, sceneData, nullptr, pass, backend)) {
|
||||
FindCompatibleSurfacePass(*builtinShader, sceneData, material, pass, backend)) {
|
||||
resolved.shader = builtinShader;
|
||||
resolved.pass = shaderPass;
|
||||
resolved.passName = shaderPass->name;
|
||||
@@ -705,18 +705,32 @@ bool BuiltinForwardPipeline::DrawVisibleItem(
|
||||
if (!materialConstants.IsValid()) {
|
||||
const BuiltinForwardMaterialData materialData = BuildBuiltinForwardMaterialData(material);
|
||||
fallbackMaterialConstants.baseColorFactor = materialData.baseColorFactor;
|
||||
static const Resources::MaterialConstantFieldDesc kFallbackMaterialConstantField = {
|
||||
Containers::String("baseColorFactor"),
|
||||
Resources::MaterialPropertyType::Float4,
|
||||
0,
|
||||
sizeof(FallbackPerMaterialConstants),
|
||||
sizeof(FallbackPerMaterialConstants)
|
||||
fallbackMaterialConstants.alphaCutoffParams = Math::Vector4(
|
||||
materialData.alphaCutoff,
|
||||
0.0f,
|
||||
0.0f,
|
||||
0.0f);
|
||||
static const Resources::MaterialConstantFieldDesc kFallbackMaterialConstantFields[] = {
|
||||
{
|
||||
Containers::String("_BaseColor"),
|
||||
Resources::MaterialPropertyType::Float4,
|
||||
0,
|
||||
sizeof(Math::Vector4),
|
||||
sizeof(Math::Vector4)
|
||||
},
|
||||
{
|
||||
Containers::String("_Cutoff"),
|
||||
Resources::MaterialPropertyType::Float,
|
||||
sizeof(Math::Vector4),
|
||||
sizeof(float),
|
||||
sizeof(Math::Vector4)
|
||||
}
|
||||
};
|
||||
materialConstants.data = &fallbackMaterialConstants;
|
||||
materialConstants.size = sizeof(fallbackMaterialConstants);
|
||||
materialConstants.layout = {
|
||||
&kFallbackMaterialConstantField,
|
||||
1,
|
||||
kFallbackMaterialConstantFields,
|
||||
2,
|
||||
sizeof(fallbackMaterialConstants)
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user