Files
XCEngine/tests/fixtures/RenderTestRhiStubs.h

796 lines
22 KiB
C++

#pragma once
#include <XCEngine/Rendering/RenderContext.h>
#include <XCEngine/RHI/RHICommandList.h>
#include <XCEngine/RHI/RHICommandQueue.h>
#include <XCEngine/RHI/RHIDescriptorPool.h>
#include <XCEngine/RHI/RHIDescriptorSet.h>
#include <XCEngine/RHI/RHIDevice.h>
#include <XCEngine/RHI/RHIPipelineLayout.h>
#include <XCEngine/RHI/RHIPipelineState.h>
#include <XCEngine/RHI/RHIResourceView.h>
#include <XCEngine/RHI/RHISampler.h>
#include <XCEngine/RHI/RHITexture.h>
#include <algorithm>
#include <array>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>
namespace XCTest {
class TestRenderResourceView final : public XCEngine::RHI::RHIResourceView {
public:
TestRenderResourceView(
XCEngine::RHI::ResourceViewType viewType,
XCEngine::RHI::ResourceViewDimension dimension,
XCEngine::RHI::Format format)
: m_viewType(viewType)
, m_dimension(dimension)
, m_format(format) {
}
void Shutdown() override {
}
void* GetNativeHandle() override {
return nullptr;
}
bool IsValid() const override {
return true;
}
XCEngine::RHI::ResourceViewType GetViewType() const override {
return m_viewType;
}
XCEngine::RHI::ResourceViewDimension GetDimension() const override {
return m_dimension;
}
XCEngine::RHI::Format GetFormat() const override {
return m_format;
}
private:
XCEngine::RHI::ResourceViewType m_viewType =
XCEngine::RHI::ResourceViewType::ShaderResource;
XCEngine::RHI::ResourceViewDimension m_dimension =
XCEngine::RHI::ResourceViewDimension::Texture2D;
XCEngine::RHI::Format m_format =
XCEngine::RHI::Format::Unknown;
};
class TestRenderTexture final : public XCEngine::RHI::RHITexture {
public:
explicit TestRenderTexture(const XCEngine::RHI::TextureDesc& desc)
: m_width(desc.width)
, m_height(desc.height)
, m_depth(desc.depth)
, m_mipLevels(desc.mipLevels)
, m_format(static_cast<XCEngine::RHI::Format>(desc.format))
, m_textureType(
static_cast<XCEngine::RHI::TextureType>(desc.textureType)) {
}
uint32_t GetWidth() const override { return m_width; }
uint32_t GetHeight() const override { return m_height; }
uint32_t GetDepth() const override { return m_depth; }
uint32_t GetMipLevels() const override { return m_mipLevels; }
XCEngine::RHI::Format GetFormat() const override { return m_format; }
XCEngine::RHI::TextureType GetTextureType() const override { return m_textureType; }
XCEngine::RHI::ResourceStates GetState() const override { return m_state; }
void SetState(XCEngine::RHI::ResourceStates state) override { m_state = state; }
void* GetNativeHandle() override { return nullptr; }
const std::string& GetName() const override { return m_name; }
void SetName(const std::string& name) override { m_name = name; }
void Shutdown() override {
}
private:
uint32_t m_width = 0u;
uint32_t m_height = 0u;
uint32_t m_depth = 1u;
uint32_t m_mipLevels = 1u;
XCEngine::RHI::Format m_format = XCEngine::RHI::Format::Unknown;
XCEngine::RHI::TextureType m_textureType =
XCEngine::RHI::TextureType::Texture2D;
XCEngine::RHI::ResourceStates m_state =
XCEngine::RHI::ResourceStates::Common;
std::string m_name;
};
class TestRenderSampler final : public XCEngine::RHI::RHISampler {
public:
void Shutdown() override {
}
void Bind(unsigned int) override {
}
void Unbind(unsigned int) override {
}
void* GetNativeHandle() override {
return nullptr;
}
unsigned int GetID() override {
return 0u;
}
};
class TestRenderPipelineLayout final : public XCEngine::RHI::RHIPipelineLayout {
public:
explicit TestRenderPipelineLayout(
const XCEngine::RHI::RHIPipelineLayoutDesc& desc)
: m_desc(desc) {
}
bool Initialize(const XCEngine::RHI::RHIPipelineLayoutDesc& desc) override {
m_desc = desc;
return true;
}
void Shutdown() override {
}
void* GetNativeHandle() override {
return nullptr;
}
private:
XCEngine::RHI::RHIPipelineLayoutDesc m_desc = {};
};
class TestRenderPipelineState final : public XCEngine::RHI::RHIPipelineState {
public:
explicit TestRenderPipelineState(
const XCEngine::RHI::GraphicsPipelineDesc& desc)
: m_inputLayout(desc.inputLayout)
, m_rasterizerState(desc.rasterizerState)
, m_blendState(desc.blendState)
, m_depthStencilState(desc.depthStencilState)
, m_topologyType(desc.topologyType) {
SetRenderTargetFormats(
desc.renderTargetCount,
desc.renderTargetFormats,
desc.depthStencilFormat);
SetSampleCount(desc.sampleCount);
SetSampleQuality(desc.sampleQuality);
}
void SetInputLayout(const XCEngine::RHI::InputLayoutDesc& layout) override {
m_inputLayout = layout;
}
void SetRasterizerState(const XCEngine::RHI::RasterizerDesc& state) override {
m_rasterizerState = state;
}
void SetBlendState(const XCEngine::RHI::BlendDesc& state) override {
m_blendState = state;
}
void SetDepthStencilState(
const XCEngine::RHI::DepthStencilStateDesc& state) override {
m_depthStencilState = state;
}
void SetTopology(uint32_t topologyType) override {
m_topologyType = topologyType;
}
void SetRenderTargetFormats(
uint32_t count,
const uint32_t* formats,
uint32_t depthFormat) override {
m_renderTargetCount = count;
m_depthStencilFormat = depthFormat;
m_renderTargetFormats.fill(0u);
for (uint32_t index = 0u;
index < count && index < m_renderTargetFormats.size();
++index) {
m_renderTargetFormats[index] = formats[index];
}
}
void SetSampleCount(uint32_t count) override {
m_sampleCount = count;
}
void SetSampleQuality(uint32_t quality) override {
m_sampleQuality = quality;
}
void SetComputeShader(XCEngine::RHI::RHIShader* shader) override {
m_computeShader = shader;
}
const XCEngine::RHI::RasterizerDesc& GetRasterizerState() const override {
return m_rasterizerState;
}
const XCEngine::RHI::BlendDesc& GetBlendState() const override {
return m_blendState;
}
const XCEngine::RHI::DepthStencilStateDesc& GetDepthStencilState() const override {
return m_depthStencilState;
}
const XCEngine::RHI::InputLayoutDesc& GetInputLayout() const override {
return m_inputLayout;
}
XCEngine::RHI::PipelineStateHash GetHash() const override {
return {};
}
XCEngine::RHI::RHIShader* GetComputeShader() const override {
return m_computeShader;
}
bool HasComputeShader() const override {
return m_computeShader != nullptr;
}
bool IsValid() const override {
return true;
}
void EnsureValid() override {
}
void Shutdown() override {
}
void Bind() override {
}
void Unbind() override {
}
void* GetNativeHandle() override {
return nullptr;
}
XCEngine::RHI::PipelineType GetType() const override {
return XCEngine::RHI::PipelineType::Graphics;
}
private:
XCEngine::RHI::InputLayoutDesc m_inputLayout = {};
XCEngine::RHI::RasterizerDesc m_rasterizerState = {};
XCEngine::RHI::BlendDesc m_blendState = {};
XCEngine::RHI::DepthStencilStateDesc m_depthStencilState = {};
uint32_t m_topologyType = 0u;
uint32_t m_renderTargetCount = 0u;
std::array<uint32_t, 8u> m_renderTargetFormats = {};
uint32_t m_depthStencilFormat = 0u;
uint32_t m_sampleCount = 1u;
uint32_t m_sampleQuality = 0u;
XCEngine::RHI::RHIShader* m_computeShader = nullptr;
};
class TestRenderDescriptorSet final : public XCEngine::RHI::RHIDescriptorSet {
public:
explicit TestRenderDescriptorSet(
const XCEngine::RHI::DescriptorSetLayoutDesc& layout) {
if (layout.bindings == nullptr || layout.bindingCount == 0u) {
return;
}
m_bindings.assign(
layout.bindings,
layout.bindings + layout.bindingCount);
uint32_t maxBinding = 0u;
for (const XCEngine::RHI::DescriptorSetLayoutBinding& binding : m_bindings) {
maxBinding = std::max(maxBinding, binding.binding);
}
m_views.resize(static_cast<size_t>(maxBinding) + 1u, nullptr);
m_samplers.resize(static_cast<size_t>(maxBinding) + 1u, nullptr);
}
void Shutdown() override {
}
void Bind() override {
}
void Unbind() override {
}
void Update(uint32_t offset, XCEngine::RHI::RHIResourceView* view) override {
if (offset >= m_views.size()) {
m_views.resize(static_cast<size_t>(offset) + 1u, nullptr);
}
m_views[offset] = view;
}
void UpdateSampler(uint32_t offset, XCEngine::RHI::RHISampler* sampler) override {
if (offset >= m_samplers.size()) {
m_samplers.resize(static_cast<size_t>(offset) + 1u, nullptr);
}
m_samplers[offset] = sampler;
}
void WriteConstant(
uint32_t,
const void* data,
size_t size,
size_t offset = 0u) override {
if (data == nullptr || size == 0u) {
return;
}
if (m_constantBuffer.size() < offset + size) {
m_constantBuffer.resize(offset + size);
}
std::memcpy(m_constantBuffer.data() + offset, data, size);
m_constantDirty = true;
}
uint32_t GetBindingCount() const override {
return static_cast<uint32_t>(m_bindings.size());
}
const XCEngine::RHI::DescriptorSetLayoutBinding* GetBindings() const override {
return m_bindings.empty()
? nullptr
: m_bindings.data();
}
void* GetConstantBufferData() override {
return m_constantBuffer.empty()
? nullptr
: m_constantBuffer.data();
}
size_t GetConstantBufferSize() const override {
return m_constantBuffer.size();
}
bool IsConstantDirty() const override {
return m_constantDirty;
}
void MarkConstantClean() override {
m_constantDirty = false;
}
private:
std::vector<XCEngine::RHI::DescriptorSetLayoutBinding> m_bindings;
std::vector<XCEngine::RHI::RHIResourceView*> m_views;
std::vector<XCEngine::RHI::RHISampler*> m_samplers;
std::vector<uint8_t> m_constantBuffer;
bool m_constantDirty = false;
};
class TestRenderDescriptorPool final : public XCEngine::RHI::RHIDescriptorPool {
public:
explicit TestRenderDescriptorPool(
const XCEngine::RHI::DescriptorPoolDesc& desc)
: m_desc(desc) {
}
bool Initialize(const XCEngine::RHI::DescriptorPoolDesc& desc) override {
m_desc = desc;
return true;
}
void Shutdown() override {
}
void* GetNativeHandle() override {
return nullptr;
}
uint32_t GetDescriptorCount() const override {
return m_desc.descriptorCount;
}
XCEngine::RHI::DescriptorHeapType GetType() const override {
return m_desc.type;
}
XCEngine::RHI::RHIDescriptorSet* AllocateSet(
const XCEngine::RHI::DescriptorSetLayoutDesc& layout) override {
return new TestRenderDescriptorSet(layout);
}
void FreeSet(XCEngine::RHI::RHIDescriptorSet* set) override {
delete set;
}
private:
XCEngine::RHI::DescriptorPoolDesc m_desc = {};
};
class TestRenderCommandList final : public XCEngine::RHI::RHICommandList {
public:
void Shutdown() override {
}
void Reset() override {
}
void Close() override {
}
void TransitionBarrier(
XCEngine::RHI::RHIResourceView*,
XCEngine::RHI::ResourceStates,
XCEngine::RHI::ResourceStates) override {
}
void BeginRenderPass(
XCEngine::RHI::RHIRenderPass*,
XCEngine::RHI::RHIFramebuffer*,
const XCEngine::RHI::Rect&,
uint32_t,
const XCEngine::RHI::ClearValue*) override {
}
void EndRenderPass() override {
++endRenderPassCalls;
}
void SetShader(XCEngine::RHI::RHIShader*) override {
}
void SetPipelineState(XCEngine::RHI::RHIPipelineState*) override {
++setPipelineStateCalls;
}
void SetGraphicsDescriptorSets(
uint32_t,
uint32_t,
XCEngine::RHI::RHIDescriptorSet**,
XCEngine::RHI::RHIPipelineLayout*) override {
}
void SetComputeDescriptorSets(
uint32_t,
uint32_t,
XCEngine::RHI::RHIDescriptorSet**,
XCEngine::RHI::RHIPipelineLayout*) override {
}
void SetPrimitiveTopology(XCEngine::RHI::PrimitiveTopology) override {
}
void SetViewport(const XCEngine::RHI::Viewport&) override {
}
void SetViewports(uint32_t, const XCEngine::RHI::Viewport*) override {
}
void SetScissorRect(const XCEngine::RHI::Rect&) override {
}
void SetScissorRects(uint32_t, const XCEngine::RHI::Rect*) override {
}
void SetRenderTargets(
uint32_t,
XCEngine::RHI::RHIResourceView**,
XCEngine::RHI::RHIResourceView*) override {
}
void SetStencilRef(uint8_t) override {
}
void SetBlendFactor(const float[4]) override {
}
void SetVertexBuffers(
uint32_t,
uint32_t,
XCEngine::RHI::RHIResourceView**,
const uint64_t*,
const uint32_t*) override {
}
void SetIndexBuffer(XCEngine::RHI::RHIResourceView*, uint64_t) override {
}
void Draw(uint32_t, uint32_t, uint32_t, uint32_t) override {
++drawCalls;
}
void DrawIndexed(
uint32_t,
uint32_t,
uint32_t,
int32_t,
uint32_t) override {
++drawIndexedCalls;
}
void Clear(float, float, float, float, uint32_t) override {
}
void ClearRenderTarget(
XCEngine::RHI::RHIResourceView*,
const float[4],
uint32_t,
const XCEngine::RHI::Rect*) override {
}
void ClearDepthStencil(
XCEngine::RHI::RHIResourceView*,
float,
uint8_t,
uint32_t,
const XCEngine::RHI::Rect*) override {
}
void CopyResource(
XCEngine::RHI::RHIResourceView*,
XCEngine::RHI::RHIResourceView*) override {
}
void Dispatch(uint32_t, uint32_t, uint32_t) override {
}
size_t endRenderPassCalls = 0u;
size_t setPipelineStateCalls = 0u;
size_t drawCalls = 0u;
size_t drawIndexedCalls = 0u;
};
class TestRenderCommandQueue final : public XCEngine::RHI::RHICommandQueue {
public:
void Shutdown() override {
}
void ExecuteCommandLists(uint32_t, void**) override {
}
void Signal(XCEngine::RHI::RHIFence*, uint64_t) override {
}
void Wait(XCEngine::RHI::RHIFence*, uint64_t) override {
}
uint64_t GetCompletedValue() override {
return 0u;
}
void WaitForIdle() override {
}
XCEngine::RHI::CommandQueueType GetType() const override {
return XCEngine::RHI::CommandQueueType::Direct;
}
uint64_t GetTimestampFrequency() const override {
return 0u;
}
void* GetNativeHandle() override {
return nullptr;
}
void WaitForPreviousFrame() override {
}
uint64_t GetCurrentFrame() const override {
return 0u;
}
};
class TestRenderDevice final : public XCEngine::RHI::RHIDevice {
public:
bool Initialize(const XCEngine::RHI::RHIDeviceDesc&) override {
return true;
}
void Shutdown() override {
}
XCEngine::RHI::RHIBuffer* CreateBuffer(
const XCEngine::RHI::BufferDesc&) override {
return nullptr;
}
XCEngine::RHI::RHITexture* CreateTexture(
const XCEngine::RHI::TextureDesc& desc) override {
++createTextureCalls;
return new TestRenderTexture(desc);
}
XCEngine::RHI::RHITexture* CreateTexture(
const XCEngine::RHI::TextureDesc& desc,
const void*,
size_t,
uint32_t) override {
return CreateTexture(desc);
}
XCEngine::RHI::RHISwapChain* CreateSwapChain(
const XCEngine::RHI::SwapChainDesc&,
XCEngine::RHI::RHICommandQueue*) override {
return nullptr;
}
XCEngine::RHI::RHICommandList* CreateCommandList(
const XCEngine::RHI::CommandListDesc&) override {
return nullptr;
}
XCEngine::RHI::RHICommandQueue* CreateCommandQueue(
const XCEngine::RHI::CommandQueueDesc&) override {
return nullptr;
}
XCEngine::RHI::RHIShader* CreateShader(
const XCEngine::RHI::ShaderCompileDesc&) override {
return nullptr;
}
XCEngine::RHI::RHIPipelineState* CreatePipelineState(
const XCEngine::RHI::GraphicsPipelineDesc& desc) override {
++createPipelineStateCalls;
return new TestRenderPipelineState(desc);
}
XCEngine::RHI::RHIPipelineLayout* CreatePipelineLayout(
const XCEngine::RHI::RHIPipelineLayoutDesc& desc) override {
++createPipelineLayoutCalls;
return new TestRenderPipelineLayout(desc);
}
XCEngine::RHI::RHIFence* CreateFence(
const XCEngine::RHI::FenceDesc&) override {
return nullptr;
}
XCEngine::RHI::RHISampler* CreateSampler(
const XCEngine::RHI::SamplerDesc&) override {
++createSamplerCalls;
return new TestRenderSampler();
}
XCEngine::RHI::RHIRenderPass* CreateRenderPass(
uint32_t,
const XCEngine::RHI::AttachmentDesc*,
const XCEngine::RHI::AttachmentDesc*) override {
return nullptr;
}
XCEngine::RHI::RHIFramebuffer* CreateFramebuffer(
XCEngine::RHI::RHIRenderPass*,
uint32_t,
uint32_t,
uint32_t,
XCEngine::RHI::RHIResourceView**,
XCEngine::RHI::RHIResourceView*) override {
return nullptr;
}
XCEngine::RHI::RHIDescriptorPool* CreateDescriptorPool(
const XCEngine::RHI::DescriptorPoolDesc& desc) override {
++createDescriptorPoolCalls;
auto* pool = new TestRenderDescriptorPool(desc);
pool->Initialize(desc);
return pool;
}
XCEngine::RHI::RHIDescriptorSet* CreateDescriptorSet(
XCEngine::RHI::RHIDescriptorPool*,
const XCEngine::RHI::DescriptorSetLayoutDesc& layout) override {
return new TestRenderDescriptorSet(layout);
}
XCEngine::RHI::RHIResourceView* CreateVertexBufferView(
XCEngine::RHI::RHIBuffer*,
const XCEngine::RHI::ResourceViewDesc&) override {
return nullptr;
}
XCEngine::RHI::RHIResourceView* CreateIndexBufferView(
XCEngine::RHI::RHIBuffer*,
const XCEngine::RHI::ResourceViewDesc&) override {
return nullptr;
}
XCEngine::RHI::RHIResourceView* CreateRenderTargetView(
XCEngine::RHI::RHITexture*,
const XCEngine::RHI::ResourceViewDesc& desc) override {
++createRenderTargetViewCalls;
return new TestRenderResourceView(
XCEngine::RHI::ResourceViewType::RenderTarget,
desc.dimension,
static_cast<XCEngine::RHI::Format>(desc.format));
}
XCEngine::RHI::RHIResourceView* CreateDepthStencilView(
XCEngine::RHI::RHITexture*,
const XCEngine::RHI::ResourceViewDesc& desc) override {
++createDepthStencilViewCalls;
return new TestRenderResourceView(
XCEngine::RHI::ResourceViewType::DepthStencil,
desc.dimension,
static_cast<XCEngine::RHI::Format>(desc.format));
}
XCEngine::RHI::RHIResourceView* CreateShaderResourceView(
XCEngine::RHI::RHIBuffer*,
const XCEngine::RHI::ResourceViewDesc&) override {
return nullptr;
}
XCEngine::RHI::RHIResourceView* CreateShaderResourceView(
XCEngine::RHI::RHITexture*,
const XCEngine::RHI::ResourceViewDesc& desc) override {
++createShaderResourceViewCalls;
return new TestRenderResourceView(
XCEngine::RHI::ResourceViewType::ShaderResource,
desc.dimension,
static_cast<XCEngine::RHI::Format>(desc.format));
}
XCEngine::RHI::RHIResourceView* CreateUnorderedAccessView(
XCEngine::RHI::RHIBuffer*,
const XCEngine::RHI::ResourceViewDesc&) override {
return nullptr;
}
XCEngine::RHI::RHIResourceView* CreateUnorderedAccessView(
XCEngine::RHI::RHITexture*,
const XCEngine::RHI::ResourceViewDesc& desc) override {
return new TestRenderResourceView(
XCEngine::RHI::ResourceViewType::UnorderedAccess,
desc.dimension,
static_cast<XCEngine::RHI::Format>(desc.format));
}
const XCEngine::RHI::RHICapabilities& GetCapabilities() const override {
return m_capabilities;
}
const XCEngine::RHI::RHIDeviceInfo& GetDeviceInfo() const override {
return m_deviceInfo;
}
void* GetNativeDevice() override {
return nullptr;
}
size_t createTextureCalls = 0u;
size_t createSamplerCalls = 0u;
size_t createRenderTargetViewCalls = 0u;
size_t createDepthStencilViewCalls = 0u;
size_t createShaderResourceViewCalls = 0u;
size_t createDescriptorPoolCalls = 0u;
size_t createPipelineLayoutCalls = 0u;
size_t createPipelineStateCalls = 0u;
private:
XCEngine::RHI::RHICapabilities m_capabilities = {};
XCEngine::RHI::RHIDeviceInfo m_deviceInfo = {};
};
inline XCEngine::Rendering::RenderContext CreateRenderContext(
XCEngine::RHI::RHIDevice& device,
XCEngine::RHI::RHICommandList& commandList,
XCEngine::RHI::RHICommandQueue& commandQueue) {
XCEngine::Rendering::RenderContext context = {};
context.device = &device;
context.commandList = &commandList;
context.commandQueue = &commandQueue;
return context;
}
} // namespace XCTest