Add pipeline layout support for graphics PSOs
This commit is contained in:
@@ -156,6 +156,7 @@ add_library(XCEngine STATIC
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLResourceView.h
|
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLResourceView.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h
|
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h
|
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLBuffer.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLBuffer.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLTexture.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLTexture.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLSampler.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLSampler.cpp
|
||||||
@@ -177,6 +178,7 @@ add_library(XCEngine STATIC
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLResourceView.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLResourceView.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorPool.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorPool.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorSet.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorSet.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLPipelineLayout.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../tests/opengl/package/src/glad.c
|
${CMAKE_CURRENT_SOURCE_DIR}/../tests/opengl/package/src/glad.c
|
||||||
|
|
||||||
# RHI Factory
|
# RHI Factory
|
||||||
|
|||||||
25
engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h
Normal file
25
engine/include/XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../RHIPipelineLayout.h"
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace RHI {
|
||||||
|
|
||||||
|
class OpenGLPipelineLayout : public RHIPipelineLayout {
|
||||||
|
public:
|
||||||
|
OpenGLPipelineLayout() = default;
|
||||||
|
~OpenGLPipelineLayout() override = default;
|
||||||
|
|
||||||
|
bool Initialize(const RHIPipelineLayoutDesc& desc) override;
|
||||||
|
void Shutdown() override;
|
||||||
|
|
||||||
|
void* GetNativeHandle() override { return m_initialized ? this : nullptr; }
|
||||||
|
const RHIPipelineLayoutDesc& GetDesc() const { return m_desc; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
RHIPipelineLayoutDesc m_desc = {};
|
||||||
|
bool m_initialized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace RHI
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace RHI {
|
namespace RHI {
|
||||||
|
|
||||||
|
class RHIPipelineLayout;
|
||||||
|
|
||||||
struct Viewport {
|
struct Viewport {
|
||||||
float topLeftX;
|
float topLeftX;
|
||||||
float topLeftY;
|
float topLeftY;
|
||||||
@@ -310,6 +312,7 @@ struct GraphicsPipelineDesc {
|
|||||||
ShaderCompileDesc vertexShader;
|
ShaderCompileDesc vertexShader;
|
||||||
ShaderCompileDesc fragmentShader;
|
ShaderCompileDesc fragmentShader;
|
||||||
ShaderCompileDesc geometryShader;
|
ShaderCompileDesc geometryShader;
|
||||||
|
RHIPipelineLayout* pipelineLayout = nullptr;
|
||||||
InputLayoutDesc inputLayout;
|
InputLayoutDesc inputLayout;
|
||||||
RasterizerDesc rasterizerState;
|
RasterizerDesc rasterizerState;
|
||||||
BlendDesc blendState;
|
BlendDesc blendState;
|
||||||
|
|||||||
@@ -523,13 +523,18 @@ RHIPipelineState* D3D12Device::CreatePipelineState(const GraphicsPipelineDesc& d
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* rootSignature = CreateRootSignature({});
|
D3D12RootSignature* rootSignature = nullptr;
|
||||||
|
if (desc.pipelineLayout != nullptr) {
|
||||||
|
auto* pipelineLayout = static_cast<D3D12PipelineLayout*>(desc.pipelineLayout);
|
||||||
|
pso->SetRootSignature(pipelineLayout->GetRootSignature());
|
||||||
|
} else {
|
||||||
|
rootSignature = CreateRootSignature({});
|
||||||
if (rootSignature == nullptr) {
|
if (rootSignature == nullptr) {
|
||||||
delete pso;
|
delete pso;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pso->SetRootSignature(rootSignature->GetRootSignature());
|
pso->SetRootSignature(rootSignature->GetRootSignature());
|
||||||
|
}
|
||||||
|
|
||||||
D3D12Shader vertexShader;
|
D3D12Shader vertexShader;
|
||||||
D3D12Shader fragmentShader;
|
D3D12Shader fragmentShader;
|
||||||
@@ -539,8 +544,10 @@ RHIPipelineState* D3D12Device::CreatePipelineState(const GraphicsPipelineDesc& d
|
|||||||
const bool geometryCompiled = !hasGeometryShader || CompileD3D12Shader(desc.geometryShader, geometryShader);
|
const bool geometryCompiled = !hasGeometryShader || CompileD3D12Shader(desc.geometryShader, geometryShader);
|
||||||
|
|
||||||
if (!vertexCompiled || !fragmentCompiled || !geometryCompiled) {
|
if (!vertexCompiled || !fragmentCompiled || !geometryCompiled) {
|
||||||
|
if (rootSignature != nullptr) {
|
||||||
rootSignature->Shutdown();
|
rootSignature->Shutdown();
|
||||||
delete rootSignature;
|
delete rootSignature;
|
||||||
|
}
|
||||||
delete pso;
|
delete pso;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -551,8 +558,10 @@ RHIPipelineState* D3D12Device::CreatePipelineState(const GraphicsPipelineDesc& d
|
|||||||
hasGeometryShader ? geometryShader.GetD3D12Bytecode() : D3D12_SHADER_BYTECODE{});
|
hasGeometryShader ? geometryShader.GetD3D12Bytecode() : D3D12_SHADER_BYTECODE{});
|
||||||
pso->EnsureValid();
|
pso->EnsureValid();
|
||||||
|
|
||||||
|
if (rootSignature != nullptr) {
|
||||||
rootSignature->Shutdown();
|
rootSignature->Shutdown();
|
||||||
delete rootSignature;
|
delete rootSignature;
|
||||||
|
}
|
||||||
|
|
||||||
if (!pso->IsValid()) {
|
if (!pso->IsValid()) {
|
||||||
delete pso;
|
delete pso;
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ bool OpenGLDescriptorPool::Initialize(const DescriptorPoolDesc& desc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDescriptorPool::Shutdown() {
|
void OpenGLDescriptorPool::Shutdown() {
|
||||||
for (auto* set : m_allocatedSets) {
|
|
||||||
delete set;
|
|
||||||
}
|
|
||||||
m_allocatedSets.clear();
|
m_allocatedSets.clear();
|
||||||
m_textureUnitAllocator = nullptr;
|
m_textureUnitAllocator = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLResourceView.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h"
|
||||||
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
#include "XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h"
|
||||||
|
#include "XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h"
|
||||||
#include "XCEngine/Debug/Logger.h"
|
#include "XCEngine/Debug/Logger.h"
|
||||||
|
|
||||||
typedef const char* (WINAPI* PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC hdc);
|
typedef const char* (WINAPI* PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC hdc);
|
||||||
@@ -476,7 +477,12 @@ RHIPipelineState* OpenGLDevice::CreatePipelineState(const GraphicsPipelineDesc&
|
|||||||
}
|
}
|
||||||
|
|
||||||
RHIPipelineLayout* OpenGLDevice::CreatePipelineLayout(const RHIPipelineLayoutDesc& desc) {
|
RHIPipelineLayout* OpenGLDevice::CreatePipelineLayout(const RHIPipelineLayoutDesc& desc) {
|
||||||
|
auto* layout = new OpenGLPipelineLayout();
|
||||||
|
if (!layout->Initialize(desc)) {
|
||||||
|
delete layout;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
RHIFence* OpenGLDevice::CreateFence(const FenceDesc& desc) {
|
RHIFence* OpenGLDevice::CreateFence(const FenceDesc& desc) {
|
||||||
|
|||||||
18
engine/src/RHI/OpenGL/OpenGLPipelineLayout.cpp
Normal file
18
engine/src/RHI/OpenGL/OpenGLPipelineLayout.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include "XCEngine/RHI/OpenGL/OpenGLPipelineLayout.h"
|
||||||
|
|
||||||
|
namespace XCEngine {
|
||||||
|
namespace RHI {
|
||||||
|
|
||||||
|
bool OpenGLPipelineLayout::Initialize(const RHIPipelineLayoutDesc& desc) {
|
||||||
|
m_desc = desc;
|
||||||
|
m_initialized = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLPipelineLayout::Shutdown() {
|
||||||
|
m_desc = {};
|
||||||
|
m_initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace RHI
|
||||||
|
} // namespace XCEngine
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "fixtures/RHITestFixture.h"
|
#include "fixtures/RHITestFixture.h"
|
||||||
|
#include "XCEngine/RHI/RHIPipelineLayout.h"
|
||||||
#include "XCEngine/RHI/RHIPipelineState.h"
|
#include "XCEngine/RHI/RHIPipelineState.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
@@ -248,3 +249,92 @@ void main() {
|
|||||||
pso->Shutdown();
|
pso->Shutdown();
|
||||||
delete pso;
|
delete pso;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(RHITestFixture, PipelineState_Create_WithPipelineLayout) {
|
||||||
|
RHIPipelineLayoutDesc layoutDesc = {};
|
||||||
|
layoutDesc.textureCount = 1;
|
||||||
|
layoutDesc.samplerCount = 1;
|
||||||
|
|
||||||
|
RHIPipelineLayout* layout = GetDevice()->CreatePipelineLayout(layoutDesc);
|
||||||
|
ASSERT_NE(layout, nullptr);
|
||||||
|
ASSERT_NE(layout->GetNativeHandle(), nullptr);
|
||||||
|
|
||||||
|
GraphicsPipelineDesc desc = {};
|
||||||
|
desc.pipelineLayout = layout;
|
||||||
|
desc.topologyType = static_cast<uint32_t>(PrimitiveTopologyType::Triangle);
|
||||||
|
desc.renderTargetFormats[0] = static_cast<uint32_t>(Format::R8G8B8A8_UNorm);
|
||||||
|
desc.depthStencilFormat = static_cast<uint32_t>(Format::Unknown);
|
||||||
|
|
||||||
|
InputElementDesc position = {};
|
||||||
|
position.semanticName = "POSITION";
|
||||||
|
position.semanticIndex = 0;
|
||||||
|
position.format = static_cast<uint32_t>(Format::R32G32B32A32_Float);
|
||||||
|
position.inputSlot = 0;
|
||||||
|
position.alignedByteOffset = 0;
|
||||||
|
desc.inputLayout.elements.push_back(position);
|
||||||
|
|
||||||
|
if (GetBackendType() == RHIType::D3D12) {
|
||||||
|
const char* hlslSource = R"(
|
||||||
|
struct VSInput {
|
||||||
|
float4 position : POSITION;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PSInput {
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
};
|
||||||
|
|
||||||
|
PSInput MainVS(VSInput input) {
|
||||||
|
PSInput output;
|
||||||
|
output.position = input.position;
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 MainPS(PSInput input) : SV_TARGET {
|
||||||
|
return float4(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
desc.vertexShader.source.assign(hlslSource, hlslSource + std::strlen(hlslSource));
|
||||||
|
desc.vertexShader.entryPoint = L"MainVS";
|
||||||
|
desc.vertexShader.profile = L"vs_5_0";
|
||||||
|
desc.vertexShader.sourceLanguage = ShaderLanguage::HLSL;
|
||||||
|
|
||||||
|
desc.fragmentShader.source.assign(hlslSource, hlslSource + std::strlen(hlslSource));
|
||||||
|
desc.fragmentShader.entryPoint = L"MainPS";
|
||||||
|
desc.fragmentShader.profile = L"ps_5_0";
|
||||||
|
desc.fragmentShader.sourceLanguage = ShaderLanguage::HLSL;
|
||||||
|
} else {
|
||||||
|
const char* vertexSource = R"(#version 430
|
||||||
|
layout(location = 0) in vec4 aPosition;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = aPosition;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
const char* fragmentSource = R"(#version 430
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
fragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
desc.vertexShader.source.assign(vertexSource, vertexSource + std::strlen(vertexSource));
|
||||||
|
desc.vertexShader.sourceLanguage = ShaderLanguage::GLSL;
|
||||||
|
desc.vertexShader.profile = L"vs_4_30";
|
||||||
|
|
||||||
|
desc.fragmentShader.source.assign(fragmentSource, fragmentSource + std::strlen(fragmentSource));
|
||||||
|
desc.fragmentShader.sourceLanguage = ShaderLanguage::GLSL;
|
||||||
|
desc.fragmentShader.profile = L"fs_4_30";
|
||||||
|
}
|
||||||
|
|
||||||
|
RHIPipelineState* pso = GetDevice()->CreatePipelineState(desc);
|
||||||
|
ASSERT_NE(pso, nullptr);
|
||||||
|
EXPECT_TRUE(pso->IsValid());
|
||||||
|
EXPECT_NE(pso->GetNativeHandle(), nullptr);
|
||||||
|
|
||||||
|
pso->Shutdown();
|
||||||
|
delete pso;
|
||||||
|
layout->Shutdown();
|
||||||
|
delete layout;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user