Add material render state and pipeline caching
This commit is contained in:
@@ -86,7 +86,10 @@ void main() {
|
||||
}
|
||||
)";
|
||||
|
||||
RHI::GraphicsPipelineDesc CreatePipelineDesc(RHI::RHIType backendType, RHI::RHIPipelineLayout* pipelineLayout) {
|
||||
RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
||||
RHI::RHIType backendType,
|
||||
RHI::RHIPipelineLayout* pipelineLayout,
|
||||
const Resources::Material* material) {
|
||||
RHI::GraphicsPipelineDesc pipelineDesc = {};
|
||||
pipelineDesc.pipelineLayout = pipelineLayout;
|
||||
pipelineDesc.topologyType = static_cast<uint32_t>(RHI::PrimitiveTopologyType::Triangle);
|
||||
@@ -94,16 +97,7 @@ RHI::GraphicsPipelineDesc CreatePipelineDesc(RHI::RHIType backendType, RHI::RHIP
|
||||
pipelineDesc.renderTargetFormats[0] = static_cast<uint32_t>(RHI::Format::R8G8B8A8_UNorm);
|
||||
pipelineDesc.depthStencilFormat = static_cast<uint32_t>(RHI::Format::D24_UNorm_S8_UInt);
|
||||
pipelineDesc.sampleCount = 1;
|
||||
|
||||
pipelineDesc.rasterizerState.fillMode = static_cast<uint32_t>(RHI::FillMode::Solid);
|
||||
pipelineDesc.rasterizerState.cullMode = static_cast<uint32_t>(RHI::CullMode::None);
|
||||
pipelineDesc.rasterizerState.frontFace = static_cast<uint32_t>(RHI::FrontFace::CounterClockwise);
|
||||
pipelineDesc.rasterizerState.depthClipEnable = true;
|
||||
|
||||
pipelineDesc.depthStencilState.depthTestEnable = true;
|
||||
pipelineDesc.depthStencilState.depthWriteEnable = true;
|
||||
pipelineDesc.depthStencilState.depthFunc = static_cast<uint32_t>(RHI::ComparisonFunc::Less);
|
||||
pipelineDesc.depthStencilState.stencilEnable = false;
|
||||
ApplyMaterialRenderState(material, pipelineDesc);
|
||||
|
||||
RHI::InputElementDesc position = {};
|
||||
position.semanticName = "POSITION";
|
||||
@@ -248,14 +242,24 @@ bool BuiltinForwardPipeline::Render(
|
||||
commandList->ClearDepthStencil(surface.GetDepthAttachment(), 1.0f, 0);
|
||||
}
|
||||
|
||||
commandList->SetPipelineState(m_pipelineState);
|
||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||
|
||||
RHI::RHIPipelineState* currentPipelineState = nullptr;
|
||||
for (const VisibleRenderItem& visibleItem : sceneData.visibleItems) {
|
||||
if (!MatchesBuiltinPass(ResolveMaterial(visibleItem), BuiltinMaterialPass::Forward)) {
|
||||
const Resources::Material* material = ResolveMaterial(visibleItem);
|
||||
if (!MatchesBuiltinPass(material, BuiltinMaterialPass::Forward)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RHI::RHIPipelineState* pipelineState = GetOrCreatePipelineState(context, material);
|
||||
if (pipelineState == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (pipelineState != currentPipelineState) {
|
||||
commandList->SetPipelineState(pipelineState);
|
||||
currentPipelineState = pipelineState;
|
||||
}
|
||||
|
||||
DrawVisibleItem(context, sceneData, visibleItem);
|
||||
}
|
||||
|
||||
@@ -387,12 +391,6 @@ bool BuiltinForwardPipeline::CreatePipelineResources(const RenderContext& contex
|
||||
return false;
|
||||
}
|
||||
|
||||
const RHI::GraphicsPipelineDesc pipelineDesc = CreatePipelineDesc(context.backendType, m_pipelineLayout);
|
||||
m_pipelineState = context.device->CreatePipelineState(pipelineDesc);
|
||||
if (m_pipelineState == nullptr || !m_pipelineState->IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::SamplerDesc samplerDesc = {};
|
||||
samplerDesc.filter = static_cast<uint32_t>(RHI::FilterMode::Linear);
|
||||
samplerDesc.addressU = static_cast<uint32_t>(RHI::TextureAddressMode::Clamp);
|
||||
@@ -441,6 +439,14 @@ bool BuiltinForwardPipeline::CreatePipelineResources(const RenderContext& contex
|
||||
void BuiltinForwardPipeline::DestroyPipelineResources() {
|
||||
m_resourceCache.Shutdown();
|
||||
|
||||
for (auto& pipelinePair : m_pipelineStates) {
|
||||
if (pipelinePair.second != nullptr) {
|
||||
pipelinePair.second->Shutdown();
|
||||
delete pipelinePair.second;
|
||||
}
|
||||
}
|
||||
m_pipelineStates.clear();
|
||||
|
||||
if (m_fallbackTextureView != nullptr) {
|
||||
m_fallbackTextureView->Shutdown();
|
||||
delete m_fallbackTextureView;
|
||||
@@ -459,12 +465,6 @@ void BuiltinForwardPipeline::DestroyPipelineResources() {
|
||||
m_sampler = nullptr;
|
||||
}
|
||||
|
||||
if (m_pipelineState != nullptr) {
|
||||
m_pipelineState->Shutdown();
|
||||
delete m_pipelineState;
|
||||
m_pipelineState = nullptr;
|
||||
}
|
||||
|
||||
if (m_pipelineLayout != nullptr) {
|
||||
m_pipelineLayout->Shutdown();
|
||||
delete m_pipelineLayout;
|
||||
@@ -511,6 +511,32 @@ void BuiltinForwardPipeline::DestroyPipelineResources() {
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
RHI::RHIPipelineState* BuiltinForwardPipeline::GetOrCreatePipelineState(
|
||||
const RenderContext& context,
|
||||
const Resources::Material* material) {
|
||||
const Resources::MaterialRenderState renderState =
|
||||
material != nullptr ? material->GetRenderState() : Resources::MaterialRenderState();
|
||||
|
||||
const auto existing = m_pipelineStates.find(renderState);
|
||||
if (existing != m_pipelineStates.end()) {
|
||||
return existing->second;
|
||||
}
|
||||
|
||||
const RHI::GraphicsPipelineDesc pipelineDesc =
|
||||
CreatePipelineDesc(context.backendType, m_pipelineLayout, material);
|
||||
RHI::RHIPipelineState* pipelineState = context.device->CreatePipelineState(pipelineDesc);
|
||||
if (pipelineState == nullptr || !pipelineState->IsValid()) {
|
||||
if (pipelineState != nullptr) {
|
||||
pipelineState->Shutdown();
|
||||
delete pipelineState;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_pipelineStates.emplace(renderState, pipelineState);
|
||||
return pipelineState;
|
||||
}
|
||||
|
||||
const Resources::Texture* BuiltinForwardPipeline::ResolveTexture(const Resources::Material* material) const {
|
||||
return material != nullptr ? FindMaterialTexture(*material) : nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user