This commit is contained in:
Dmitry 2019-06-02 23:42:07 +03:00
parent 37436a8de2
commit 90309c7a43
70 changed files with 5884 additions and 569 deletions

View File

@ -3,12 +3,6 @@
using namespace verus;
using namespace verus::CGI;
ID3D12GraphicsCommandList4* CommandBufferD3D12::GetGraphicsCommandList() const
{
VERUS_QREF_RENDERER;
return _pCommandLists[renderer->GetRingBufferIndex()].Get();
}
CommandBufferD3D12::CommandBufferD3D12()
{
}
@ -21,75 +15,104 @@ CommandBufferD3D12::~CommandBufferD3D12()
void CommandBufferD3D12::Init()
{
VERUS_INIT();
VERUS_QREF_RENDERER_D3D12;
VERUS_FOR(i, BaseRenderer::s_ringBufferSize)
_pCommandLists[i] = pRendererD3D12->CreateCommandList(D3D12_COMMAND_LIST_TYPE_DIRECT, pRendererD3D12->GetD3DCommandAllocator(i));
}
void CommandBufferD3D12::Done()
{
VERUS_FOR(i, BaseRenderer::s_ringBufferSize)
_pCommandLists[i].Reset();
VERUS_DONE(CommandBufferD3D12);
}
void CommandBufferD3D12::Begin()
{
VERUS_QREF_RENDERER_D3D12;
HRESULT hr = 0;
if (FAILED(hr = GetGraphicsCommandList()->Reset(nullptr, nullptr)))
if (FAILED(hr = GetD3DGraphicsCommandList()->Reset(pRendererD3D12->GetD3DCommandAllocator(pRendererD3D12->GetRingBufferIndex()), nullptr)))
throw VERUS_RUNTIME_ERROR << "Reset(), hr=" << VERUS_HR(hr);
}
void CommandBufferD3D12::End()
{
HRESULT hr = 0;
if (FAILED(hr = GetGraphicsCommandList()->Close()))
if (FAILED(hr = GetD3DGraphicsCommandList()->Close()))
throw VERUS_RUNTIME_ERROR << "Close(), hr=" << VERUS_HR(hr);
}
void CommandBufferD3D12::BeginRenderPass()
void CommandBufferD3D12::BeginRenderPass(int renderPassID, int framebufferID, std::initializer_list<Vector4> ilClearValues, PcVector4 pRenderArea)
{
D3D12_RENDER_PASS_RENDER_TARGET_DESC rtDesc = {};
D3D12_RENDER_PASS_DEPTH_STENCIL_DESC dsDesc = {};
GetGraphicsCommandList()->BeginRenderPass(0, &rtDesc, &dsDesc, D3D12_RENDER_PASS_FLAG_NONE);
GetD3DGraphicsCommandList()->BeginRenderPass(0, &rtDesc, &dsDesc, D3D12_RENDER_PASS_FLAG_NONE);
}
void CommandBufferD3D12::EndRenderPass()
{
GetGraphicsCommandList()->EndRenderPass();
GetD3DGraphicsCommandList()->EndRenderPass();
}
void CommandBufferD3D12::BindVertexBuffers()
void CommandBufferD3D12::BindVertexBuffers(GeometryPtr geo)
{
GetGraphicsCommandList()->IASetVertexBuffers(0, 1, nullptr);
auto& geoD3D12 = static_cast<RGeometryD3D12>(*geo);
GetD3DGraphicsCommandList()->IASetVertexBuffers(0, 1, geoD3D12.GetD3DVertexBufferView());
}
void CommandBufferD3D12::BindIndexBuffer()
void CommandBufferD3D12::BindIndexBuffer(GeometryPtr geo)
{
GetGraphicsCommandList()->IASetIndexBuffer(nullptr);
auto& geoD3D12 = static_cast<RGeometryD3D12>(*geo);
GetD3DGraphicsCommandList()->IASetIndexBuffer(geoD3D12.GetD3DIndexBufferView());
}
void CommandBufferD3D12::SetScissor()
void CommandBufferD3D12::SetScissor(std::initializer_list<Vector4> il)
{
GetGraphicsCommandList()->RSSetScissorRects(1, nullptr);
CD3DX12_RECT rcD3D12[VERUS_CGI_MAX_RT];
int num = 0;
for (auto& rc : il)
rcD3D12[num++] = CD3DX12_RECT(
static_cast<LONG>(rc.getX()),
static_cast<LONG>(rc.getY()),
static_cast<LONG>(rc.getZ()),
static_cast<LONG>(rc.getW()));
GetD3DGraphicsCommandList()->RSSetScissorRects(num, rcD3D12);
}
void CommandBufferD3D12::SetViewport()
void CommandBufferD3D12::SetViewport(std::initializer_list<Vector4> il, float minDepth, float maxDepth)
{
GetGraphicsCommandList()->RSSetViewports(1, nullptr);
CD3DX12_VIEWPORT vpD3D12[VERUS_CGI_MAX_RT];
int num = 0;
for (auto& rc : il)
vpD3D12[num++] = CD3DX12_VIEWPORT(rc.getX(), rc.getY(), rc.Width(), rc.Height(), minDepth, maxDepth);
GetD3DGraphicsCommandList()->RSSetViewports(num, vpD3D12);
}
void CommandBufferD3D12::BindPipeline()
void CommandBufferD3D12::BindPipeline(PipelinePtr pipe)
{
GetGraphicsCommandList()->SetPipelineState(nullptr);
auto& pipeD3D12 = static_cast<RPipelineD3D12>(*pipe);
GetD3DGraphicsCommandList()->SetPipelineState(pipeD3D12.GetD3DPipelineState());
GetD3DGraphicsCommandList()->SetGraphicsRootSignature(pipeD3D12.GetD3DRootSignature());
GetD3DGraphicsCommandList()->IASetPrimitiveTopology(pipeD3D12.GetPrimitiveTopology());
}
void CommandBufferD3D12::PushConstant(PipelinePtr pipe, int offset, int size, const void* p)
{
GetD3DGraphicsCommandList()->SetGraphicsRoot32BitConstants(0, size, p, offset);
}
void CommandBufferD3D12::PipelineBarrier(TexturePtr tex, ImageLayout oldLayout, ImageLayout newLayout)
{
PTextureD3D12 pTex = static_cast<PTextureD3D12>(&(*tex));
auto& texD3D12 = static_cast<RTextureD3D12>(*tex);
D3D12_RESOURCE_BARRIER rb = {};
rb.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
rb.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
rb.Transition.pResource = pTex->GetID3D12Resource();
rb.Transition.pResource = texD3D12.GetD3DResource();
rb.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
rb.Transition.StateBefore = ToNativeImageLayout(oldLayout);
rb.Transition.StateAfter = ToNativeImageLayout(newLayout);
GetGraphicsCommandList()->ResourceBarrier(1, &rb);
GetD3DGraphicsCommandList()->ResourceBarrier(1, &rb);
}
void CommandBufferD3D12::Clear(ClearFlags clearFlags)
@ -97,21 +120,27 @@ void CommandBufferD3D12::Clear(ClearFlags clearFlags)
VERUS_QREF_RENDERER;
if (clearFlags & ClearFlags::color)
GetGraphicsCommandList()->ClearRenderTargetView({}, renderer.GetClearColor().ToPointer(), 0, nullptr);
GetD3DGraphicsCommandList()->ClearRenderTargetView({}, renderer.GetClearColor().ToPointer(), 0, nullptr);
UINT cf = 0;
if (clearFlags & ClearFlags::depth) cf |= D3D12_CLEAR_FLAG_DEPTH;
if (clearFlags & ClearFlags::stencil) cf |= D3D12_CLEAR_FLAG_STENCIL;
if (cf)
GetGraphicsCommandList()->ClearDepthStencilView({}, static_cast<D3D12_CLEAR_FLAGS>(cf), 0, 0, 0, nullptr);
GetD3DGraphicsCommandList()->ClearDepthStencilView({}, static_cast<D3D12_CLEAR_FLAGS>(cf), 0, 0, 0, nullptr);
}
void CommandBufferD3D12::Draw()
void CommandBufferD3D12::Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
{
GetGraphicsCommandList()->DrawInstanced(0, 0, 0, 0);
GetD3DGraphicsCommandList()->DrawInstanced(vertexCount, instanceCount, firstVertex, firstInstance);
}
void CommandBufferD3D12::DrawIndexed()
void CommandBufferD3D12::DrawIndexed(int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance)
{
GetGraphicsCommandList()->DrawIndexedInstanced(0, 0, 0, 0, 0);
GetD3DGraphicsCommandList()->DrawIndexedInstanced(indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
}
ID3D12GraphicsCommandList4* CommandBufferD3D12::GetD3DGraphicsCommandList() const
{
VERUS_QREF_RENDERER;
return _pCommandLists[renderer->GetRingBufferIndex()].Get();
}

View File

@ -8,8 +8,6 @@ namespace verus
{
ComPtr<ID3D12GraphicsCommandList4> _pCommandLists[BaseRenderer::s_ringBufferSize];
ID3D12GraphicsCommandList4* GetGraphicsCommandList() const;
public:
CommandBufferD3D12();
virtual ~CommandBufferD3D12() override;
@ -20,20 +18,28 @@ namespace verus
virtual void Begin() override;
virtual void End() override;
virtual void BeginRenderPass() override;
virtual void BeginRenderPass(int renderPassID, int framebufferID, std::initializer_list<Vector4> ilClearValues, PcVector4 pRenderArea) override;
virtual void EndRenderPass() override;
virtual void BindVertexBuffers() override;
virtual void BindIndexBuffer() override;
virtual void BindVertexBuffers(GeometryPtr geo) override;
virtual void BindIndexBuffer(GeometryPtr geo) override;
virtual void SetScissor() override;
virtual void SetViewport() override;
virtual void SetScissor(std::initializer_list<Vector4> il) override;
virtual void SetViewport(std::initializer_list<Vector4> il, float minDepth, float maxDepth) override;
virtual void BindPipeline() override;
virtual void BindPipeline(PipelinePtr pipe) override;
virtual void PushConstant(PipelinePtr pipe, int offset, int size, const void* p) override;
virtual void PipelineBarrier(TexturePtr tex, ImageLayout oldLayout, ImageLayout newLayout) override;
virtual void Clear(ClearFlags clearFlags) override;
virtual void Draw() override;
virtual void DrawIndexed() override;
virtual void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) override;
virtual void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) override;
//
// D3D12
//
ID3D12GraphicsCommandList4* GetD3DGraphicsCommandList() const;
};
VERUS_TYPEDEFS(CommandBufferD3D12);
}

View File

@ -5,6 +5,8 @@ using namespace verus::CGI;
GeometryD3D12::GeometryD3D12()
{
VERUS_ZERO_MEM(_vertexBufferView);
VERUS_ZERO_MEM(_indexBufferView);
}
GeometryD3D12::~GeometryD3D12()
@ -15,9 +17,130 @@ GeometryD3D12::~GeometryD3D12()
void GeometryD3D12::Init(RcGeometryDesc desc)
{
VERUS_INIT();
_32bitIndices = desc._32bitIndices;
_vInputElementDesc.reserve(GetNumInputElementDesc(desc._pInputElementDesc));
int i = 0;
while (desc._pInputElementDesc[i]._offset >= 0)
{
int binding = desc._pInputElementDesc[i]._binding;
D3D12_INPUT_CLASSIFICATION inputClassification = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
UINT instanceDataStepRate = 0;
if (binding < 0)
{
binding = -binding;
_bindingInstMask |= (1 << binding);
inputClassification = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
instanceDataStepRate = 1;
}
D3D12_INPUT_ELEMENT_DESC ieDesc =
{
ToNativeSemanticName(desc._pInputElementDesc[i]._usage),
static_cast<UINT>(desc._pInputElementDesc[i]._usageIndex),
ToNativeFormat(desc._pInputElementDesc[i]._usage, desc._pInputElementDesc[i]._type, desc._pInputElementDesc[i]._components),
static_cast<UINT>(binding),
static_cast<UINT>(desc._pInputElementDesc[i]._offset),
inputClassification,
instanceDataStepRate
};
_vInputElementDesc.push_back(ieDesc);
i++;
}
_vStrides.reserve(GetNumBindings(desc._pInputElementDesc));
i = 0;
while (desc._pStrides[i] > 0)
{
_vStrides.push_back(desc._pStrides[i]);
i++;
}
}
void GeometryD3D12::Done()
{
VERUS_DONE(GeometryD3D12);
}
void GeometryD3D12::BufferDataVB(const void* p, int num, int binding)
{
const int elementSize = _vStrides[binding];
BufferData(&_pVertexBuffer, &_pStagingVertexBuffer, num, elementSize, p);
_vertexBufferView.BufferLocation = _pVertexBuffer->GetGPUVirtualAddress();
_vertexBufferView.SizeInBytes = num * elementSize;
_vertexBufferView.StrideInBytes = elementSize;
}
void GeometryD3D12::BufferDataIB(const void* p, int num)
{
const int elementSize = _32bitIndices ? sizeof(UINT32) : sizeof(UINT16);
BufferData(&_pIndexBuffer, &_pStagingIndexBuffer, num, elementSize, p);
_indexBufferView.BufferLocation = _pIndexBuffer->GetGPUVirtualAddress();
_indexBufferView.SizeInBytes = num * elementSize;
_indexBufferView.Format = _32bitIndices ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT;
}
void GeometryD3D12::BufferData(
ID3D12Resource** ppDestRes,
ID3D12Resource** ppTempRes,
size_t numElements,
size_t elementSize,
const void* p,
D3D12_RESOURCE_FLAGS flags)
{
VERUS_QREF_RENDERER;
VERUS_QREF_RENDERER_D3D12;
HRESULT hr = 0;
const size_t bufferSize = numElements * elementSize;
if (FAILED(hr = pRendererD3D12->GetD3DDevice()->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(bufferSize, flags),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(ppDestRes))))
throw VERUS_RUNTIME_ERROR << "CreateCommittedResource(D3D12_HEAP_TYPE_DEFAULT), hr=" << VERUS_HR(hr);
if (p)
{
if (FAILED(hr = pRendererD3D12->GetD3DDevice()->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(bufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(ppTempRes))))
throw VERUS_RUNTIME_ERROR << "CreateCommittedResource(D3D12_HEAP_TYPE_UPLOAD), hr=" << VERUS_HR(hr);
auto pCmdList = static_cast<PCommandBufferD3D12>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList();
D3D12_SUBRESOURCE_DATA sd = {};
sd.pData = p;
sd.RowPitch = bufferSize;
sd.SlicePitch = sd.RowPitch;
UpdateSubresources(pCmdList,
*ppDestRes,
*ppTempRes,
0, 0, 1, &sd);
}
}
D3D12_INPUT_LAYOUT_DESC GeometryD3D12::GetD3DInputLayoutDesc() const
{
return { _vInputElementDesc.data(), Utils::Cast32(_vInputElementDesc.size()) };
}
const D3D12_VERTEX_BUFFER_VIEW* GeometryD3D12::GetD3DVertexBufferView() const
{
return &_vertexBufferView;
}
const D3D12_INDEX_BUFFER_VIEW* GeometryD3D12::GetD3DIndexBufferView() const
{
return &_indexBufferView;
}

View File

@ -6,8 +6,14 @@ namespace verus
{
class GeometryD3D12 : public BaseGeometry
{
ComPtr<ID3D12Resource> _pVertexBuffer;
ComPtr<ID3D12Resource> _pIndexBuffer;
ComPtr<ID3D12Resource> _pVertexBuffer;
ComPtr<ID3D12Resource> _pIndexBuffer;
ComPtr<ID3D12Resource> _pStagingVertexBuffer;
ComPtr<ID3D12Resource> _pStagingIndexBuffer;
D3D12_VERTEX_BUFFER_VIEW _vertexBufferView;
D3D12_INDEX_BUFFER_VIEW _indexBufferView;
Vector<D3D12_INPUT_ELEMENT_DESC> _vInputElementDesc;
Vector<int> _vStrides;
public:
GeometryD3D12();
@ -15,6 +21,26 @@ namespace verus
virtual void Init(RcGeometryDesc desc) override;
virtual void Done() override;
virtual void BufferDataVB(const void* p, int num, int binding) override;
virtual void BufferDataIB(const void* p, int num) override;
//
// D3D12
//
void BufferData(
ID3D12Resource** ppDestRes,
ID3D12Resource** ppTempRes,
size_t numElements,
size_t elementSize,
const void* p,
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE);
D3D12_INPUT_LAYOUT_DESC GetD3DInputLayoutDesc() const;
const D3D12_VERTEX_BUFFER_VIEW* GetD3DVertexBufferView() const;
const D3D12_INDEX_BUFFER_VIEW* GetD3DIndexBufferView() const;
};
VERUS_TYPEDEFS(GeometryD3D12);
}

View File

@ -3,7 +3,7 @@
using namespace verus;
using namespace verus::CGI;
DXGI_FORMAT ToNativeFormat(Format format)
DXGI_FORMAT CGI::ToNativeFormat(Format format)
{
switch (format)
{
@ -101,3 +101,91 @@ D3D12_PRIMITIVE_TOPOLOGY_TYPE CGI::ToNativePrimitiveTopologyType(PrimitiveTopolo
default: throw VERUS_RECOVERABLE << "ToNativePrimitiveTopologyType()";
}
}
CSZ CGI::ToNativeSemanticName(IeUsage usage)
{
static const CSZ names[] =
{
"POSITION", // IeUsage::position
"BLENDWEIGHT", // IeUsage::blendWeight
"BLENDINDICES", // IeUsage::blendIndices
"NORMAL", // IeUsage::normal
"PSIZE", // IeUsage::psize
"TEXCOORD", // IeUsage::texCoord
"TEXCOORD", // IeUsage::tangent
"TEXCOORD", // IeUsage::binormal
"COLOR" // IeUsage::color
};
return names[+usage];
}
DXGI_FORMAT CGI::ToNativeFormat(IeUsage usage, IeType type, int components)
{
VERUS_RT_ASSERT(components >= 1 && components <= 4);
int index = components - 1;
static const DXGI_FORMAT floats[] =
{
DXGI_FORMAT_R32_FLOAT,
DXGI_FORMAT_R32G32_FLOAT,
DXGI_FORMAT_R32G32B32_FLOAT,
DXGI_FORMAT_R32G32B32A32_FLOAT
};
static const DXGI_FORMAT bytes[] =
{
DXGI_FORMAT_R8G8B8A8_UINT,
DXGI_FORMAT_R8G8B8A8_UINT,
DXGI_FORMAT_R8G8B8A8_UINT,
DXGI_FORMAT_R8G8B8A8_UINT,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_SNORM,
DXGI_FORMAT_R8G8B8A8_SNORM,
DXGI_FORMAT_R8G8B8A8_SNORM,
DXGI_FORMAT_R8G8B8A8_SNORM
};
static const DXGI_FORMAT shorts[] =
{
DXGI_FORMAT_R16G16_SINT,
DXGI_FORMAT_R16G16_SINT,
DXGI_FORMAT_R16G16B16A16_SINT,
DXGI_FORMAT_R16G16B16A16_SINT,
DXGI_FORMAT_R16G16_SNORM,
DXGI_FORMAT_R16G16_SNORM,
DXGI_FORMAT_R16G16B16A16_SNORM,
DXGI_FORMAT_R16G16B16A16_SNORM
};
switch (type)
{
case IeType::_float:
{
return floats[index];
}
break;
case IeType::_ubyte:
{
VERUS_RT_ASSERT(4 == components);
switch (usage)
{
case IeUsage::normal: index += 8; break; // SNORM.
case IeUsage::color: index += 4; break; // UNORM.
}
return bytes[index];
}
break;
case IeType::_short:
{
VERUS_RT_ASSERT(2 == components || 4 == components);
switch (usage)
{
case IeUsage::tangent:
case IeUsage::binormal:
index += 4; break; // SNORM.
}
return shorts[index];
}
break;
default: throw VERUS_RECOVERABLE << "ToNativeFormat(), IeType=?";
}
}

View File

@ -14,5 +14,8 @@ namespace verus
D3D_PRIMITIVE_TOPOLOGY ToNativePrimitiveTopology(PrimitiveTopology primitiveTopology);
D3D12_PRIMITIVE_TOPOLOGY_TYPE ToNativePrimitiveTopologyType(PrimitiveTopology primitiveTopology);
CSZ ToNativeSemanticName(IeUsage usage);
DXGI_FORMAT ToNativeFormat(IeUsage usage, IeType type, int components);
}
}

View File

@ -18,30 +18,39 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
VERUS_QREF_RENDERER_D3D12;
HRESULT hr = 0;
RcShaderD3D12 shader = static_cast<RcShaderD3D12>(desc._shader);
_topology = ToNativePrimitiveTopology(desc._topology);
CreateRootSignature();
RcGeometryD3D12 geo = static_cast<RcGeometryD3D12>(*desc._geometry);
RcShaderD3D12 shader = static_cast<RcShaderD3D12>(*desc._shader);
auto ToBytecode = [](ID3DBlob* pBlob) -> D3D12_SHADER_BYTECODE
{
D3D12_SHADER_BYTECODE bytecode;
bytecode.pShaderBytecode = pBlob->GetBufferPointer();
bytecode.BytecodeLength = pBlob->GetBufferSize();
D3D12_SHADER_BYTECODE bytecode = {};
if (pBlob)
{
bytecode.pShaderBytecode = pBlob->GetBufferPointer();
bytecode.BytecodeLength = pBlob->GetBufferSize();
}
return bytecode;
};
D3D12_GRAPHICS_PIPELINE_STATE_DESC gpsDesc = {};
gpsDesc.pRootSignature = nullptr;
gpsDesc.VS = ToBytecode(shader.GetID3DBlob(desc._shaderBranch, BaseShader::Stage::vs).Get());
gpsDesc.PS = ToBytecode(shader.GetID3DBlob(desc._shaderBranch, BaseShader::Stage::fs).Get());
gpsDesc.DS = ToBytecode(shader.GetID3DBlob(desc._shaderBranch, BaseShader::Stage::ds).Get());
gpsDesc.HS = ToBytecode(shader.GetID3DBlob(desc._shaderBranch, BaseShader::Stage::hs).Get());
gpsDesc.GS = ToBytecode(shader.GetID3DBlob(desc._shaderBranch, BaseShader::Stage::gs).Get());
gpsDesc.pRootSignature = _pRootSignature.Get();
gpsDesc.VS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::vs));
gpsDesc.PS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::fs));
gpsDesc.DS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::ds));
gpsDesc.HS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::hs));
gpsDesc.GS = ToBytecode(shader.GetD3DBlob(desc._shaderBranch, BaseShader::Stage::gs));
gpsDesc.StreamOutput = {};
gpsDesc.BlendState = {};
gpsDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
gpsDesc.SampleMask = UINT_MAX;
gpsDesc.RasterizerState.FillMode = ToNativePolygonMode(desc._rasterizationState._polygonMode);
gpsDesc.RasterizerState.CullMode = ToNativeCullMode(desc._rasterizationState._cullMode);
gpsDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE /*ToNativeCullMode(desc._rasterizationState._cullMode)*/;
gpsDesc.RasterizerState.FrontCounterClockwise = FALSE;
gpsDesc.RasterizerState.DepthBias = desc._rasterizationState._depthBiasConstantFactor;
gpsDesc.RasterizerState.DepthBias = static_cast<INT>(desc._rasterizationState._depthBiasConstantFactor);
gpsDesc.RasterizerState.DepthBiasClamp = desc._rasterizationState._depthBiasClamp;
gpsDesc.RasterizerState.SlopeScaledDepthBias = desc._rasterizationState._depthBiasSlopeFactor;
gpsDesc.RasterizerState.DepthClipEnable = desc._rasterizationState._depthClampEnable;
@ -51,7 +60,7 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
gpsDesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
gpsDesc.DepthStencilState = {};
//gpsDesc.InputLayout = nullptr;
gpsDesc.InputLayout = geo.GetD3DInputLayoutDesc();
gpsDesc.IBStripCutValue = desc._primitiveRestartEnable ? D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF : D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
gpsDesc.PrimitiveTopologyType = ToNativePrimitiveTopologyType(desc._topology);
gpsDesc.NumRenderTargets = 1;
@ -62,7 +71,7 @@ void PipelineD3D12::Init(RcPipelineDesc desc)
gpsDesc.CachedPSO = { nullptr, 0 };
gpsDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
if (FAILED(hr = pRendererD3D12->GetDevice()->CreateGraphicsPipelineState(&gpsDesc, IID_PPV_ARGS(&_pPipelineState))))
if (FAILED(hr = pRendererD3D12->GetD3DDevice()->CreateGraphicsPipelineState(&gpsDesc, IID_PPV_ARGS(&_pPipelineState))))
throw VERUS_RUNTIME_ERROR << "CreateGraphicsPipelineState(), hr=" << VERUS_HR(hr);
}
@ -70,3 +79,34 @@ void PipelineD3D12::Done()
{
VERUS_DONE(PipelineD3D12);
}
void PipelineD3D12::CreateRootSignature()
{
VERUS_QREF_RENDERER_D3D12;
HRESULT hr = 0;
D3D12_FEATURE_DATA_ROOT_SIGNATURE featureSupportData = {};
featureSupportData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1;
if (FAILED(pRendererD3D12->GetD3DDevice()->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &featureSupportData, sizeof(featureSupportData))))
featureSupportData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;
const D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;
CD3DX12_ROOT_PARAMETER1 rootParameters[1];
rootParameters[0].InitAsConstants(sizeof(Matrix4) / 4, 0, 0, D3D12_SHADER_VISIBILITY_VERTEX);
CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc;
rootSignatureDesc.Init_1_1(VERUS_ARRAY_LENGTH(rootParameters), rootParameters, 0, nullptr, rootSignatureFlags);
ComPtr<ID3DBlob> pRootSignatureBlob;
ComPtr<ID3DBlob> pErrorBlob;
if (FAILED(hr = D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, featureSupportData.HighestVersion, &pRootSignatureBlob, &pErrorBlob)))
throw VERUS_RUNTIME_ERROR << "D3DX12SerializeVersionedRootSignature(), hr=" << VERUS_HR(hr);
if (FAILED(hr = pRendererD3D12->GetD3DDevice()->CreateRootSignature(0, pRootSignatureBlob->GetBufferPointer(), pRootSignatureBlob->GetBufferSize(), IID_PPV_ARGS(&_pRootSignature))))
throw VERUS_RUNTIME_ERROR << "CreateRootSignature(), hr=" << VERUS_HR(hr);
}

View File

@ -7,6 +7,8 @@ namespace verus
class PipelineD3D12 : public BasePipeline
{
ComPtr<ID3D12PipelineState> _pPipelineState;
ComPtr<ID3D12RootSignature> _pRootSignature;
D3D_PRIMITIVE_TOPOLOGY _topology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
public:
PipelineD3D12();
@ -14,6 +16,16 @@ namespace verus
virtual void Init(RcPipelineDesc desc) override;
virtual void Done() override;
void CreateRootSignature();
//
// D3D12
//
ID3D12PipelineState* GetD3DPipelineState() const { return _pPipelineState.Get(); }
ID3D12RootSignature* GetD3DRootSignature() const { return _pRootSignature.Get(); }
D3D_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return _topology; }
};
VERUS_TYPEDEFS(PipelineD3D12);
}

View File

@ -27,16 +27,13 @@ void RendererD3D12::Init()
void RendererD3D12::Done()
{
if (_pCommandQueue)
QueueWaitIdle();
WaitIdle();
if (_hFence != INVALID_HANDLE_VALUE)
{
CloseHandle(_hFence);
_hFence = INVALID_HANDLE_VALUE;
}
_pFence.Reset();
VERUS_FOR(i, s_ringBufferSize)
_pCommandLists[i].Reset();
VERUS_FOR(i, s_ringBufferSize)
_mapCommandAllocators[i].clear();
_dSwapChainBuffersRTVs.Reset();
@ -79,10 +76,10 @@ ComPtr<IDXGIAdapter4> RendererD3D12::GetAdapter(ComPtr<IDXGIFactory6> pFactory)
bool RendererD3D12::CheckFeatureSupportAllowTearing(ComPtr<IDXGIFactory6> pFactory)
{
BOOL data = FALSE;
if (FAILED(pFactory->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &data, sizeof(data))))
data = FALSE;
return data == TRUE;
BOOL featureSupportData = FALSE;
if (FAILED(pFactory->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &featureSupportData, sizeof(featureSupportData))))
featureSupportData = FALSE;
return featureSupportData == TRUE;
}
void RendererD3D12::CreateSwapChainBuffersRTVs()
@ -159,9 +156,6 @@ void RendererD3D12::InitD3D()
VERUS_FOR(i, s_ringBufferSize)
_mapCommandAllocators[i][std::this_thread::get_id()] = CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT);
VERUS_FOR(i, s_ringBufferSize)
_pCommandLists[i] = CreateCommandList(D3D12_COMMAND_LIST_TYPE_DIRECT, _mapCommandAllocators[i][std::this_thread::get_id()]);
_pFence = CreateFence();
_hFence = CreateEvent(nullptr, FALSE, FALSE, nullptr);
}
@ -188,10 +182,10 @@ ComPtr<ID3D12CommandAllocator> RendererD3D12::CreateCommandAllocator(D3D12_COMMA
return pCommandAllocator;
}
ComPtr<ID3D12GraphicsCommandList> RendererD3D12::CreateCommandList(D3D12_COMMAND_LIST_TYPE type, ComPtr<ID3D12CommandAllocator> pCommandAllocator)
ComPtr<ID3D12GraphicsCommandList4> RendererD3D12::CreateCommandList(D3D12_COMMAND_LIST_TYPE type, ComPtr<ID3D12CommandAllocator> pCommandAllocator)
{
HRESULT hr = 0;
ComPtr<ID3D12GraphicsCommandList> pGraphicsCommandList;
ComPtr<ID3D12GraphicsCommandList4> pGraphicsCommandList;
if (FAILED(hr = _pDevice->CreateCommandList(0, type, pCommandAllocator.Get(), nullptr, IID_PPV_ARGS(&pGraphicsCommandList))))
throw VERUS_RUNTIME_ERROR << "CreateCommandList(), hr=" << VERUS_HR(hr);
if (FAILED(hr = pGraphicsCommandList->Close()))
@ -242,8 +236,11 @@ void RendererD3D12::WaitForFenceValue(UINT64 value)
void RendererD3D12::QueueWaitIdle()
{
const UINT64 value = QueueSignal();
WaitForFenceValue(value);
if (_pCommandQueue)
{
const UINT64 value = QueueSignal();
WaitForFenceValue(value);
}
}
D3D12_RESOURCE_BARRIER RendererD3D12::MakeResourceBarrierTransition(ID3D12Resource* pResource, D3D12_RESOURCE_STATES before, D3D12_RESOURCE_STATES after)
@ -258,39 +255,49 @@ D3D12_RESOURCE_BARRIER RendererD3D12::MakeResourceBarrierTransition(ID3D12Resour
return rb;
}
void RendererD3D12::BeginFrame()
void RendererD3D12::BeginFrame(bool present)
{
VERUS_QREF_RENDERER;
HRESULT hr = 0;
WaitForFenceValue(_fenceValues[_ringBufferIndex]);
_swapChainBufferIndex = _pSwapChain->GetCurrentBackBufferIndex();
if (present)
_swapChainBufferIndex = _pSwapChain->GetCurrentBackBufferIndex();
auto pCommandAllocator = _mapCommandAllocators[_ringBufferIndex][std::this_thread::get_id()];
if (FAILED(hr = pCommandAllocator->Reset()))
throw VERUS_RUNTIME_ERROR << "Reset(), hr=" << VERUS_HR(hr);
if (FAILED(hr = _pCommandLists[_ringBufferIndex]->Reset(pCommandAllocator.Get(), nullptr)))
throw VERUS_RUNTIME_ERROR << "Reset(), hr=" << VERUS_HR(hr);
auto pBackBuffer = _vSwapChainBuffers[_swapChainBufferIndex];
const auto rb = MakeResourceBarrierTransition(pBackBuffer.Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
_pCommandLists[_ringBufferIndex]->ResourceBarrier(1, &rb);
renderer.GetCommandBuffer()->Begin();
if (present)
{
auto pBackBuffer = _vSwapChainBuffers[_swapChainBufferIndex];
const auto rb = MakeResourceBarrierTransition(pBackBuffer.Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList()->ResourceBarrier(1, &rb);
}
}
void RendererD3D12::EndFrame()
void RendererD3D12::EndFrame(bool present)
{
VERUS_QREF_RENDERER;
HRESULT hr = 0;
auto pBackBuffer = _vSwapChainBuffers[_swapChainBufferIndex];
const auto rb = MakeResourceBarrierTransition(pBackBuffer.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
_pCommandLists[_ringBufferIndex]->ResourceBarrier(1, &rb);
if (present)
{
auto pBackBuffer = _vSwapChainBuffers[_swapChainBufferIndex];
const auto rb = MakeResourceBarrierTransition(pBackBuffer.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList()->ResourceBarrier(1, &rb);
}
if (FAILED(hr = _pCommandLists[_ringBufferIndex]->Close()))
throw VERUS_RUNTIME_ERROR << "Close(), hr=" << VERUS_HR(hr);
ID3D12CommandList* ppCommandLists[] = { _pCommandLists[_ringBufferIndex].Get() };
renderer.GetCommandBuffer()->End();
ID3D12CommandList* ppCommandLists[] = { static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList() };
_pCommandQueue->ExecuteCommandLists(VERUS_ARRAY_LENGTH(ppCommandLists), ppCommandLists);
_fenceValues[_ringBufferIndex] = QueueSignal();
_ringBufferIndex = (_ringBufferIndex + 1) % s_ringBufferSize;
}
void RendererD3D12::Present()
@ -304,8 +311,6 @@ void RendererD3D12::Present()
const UINT flags = g_TearingSupported && !g_VSync ? DXGI_PRESENT_ALLOW_TEARING : 0;
if (FAILED(hr = _pSwapChain->Present(syncInterval, flags)))
throw VERUS_RUNTIME_ERROR << "Present(), hr=" << VERUS_HR(hr);
_ringBufferIndex = (_ringBufferIndex + 1) % s_ringBufferSize;
}
void RendererD3D12::Clear(UINT32 flags)
@ -314,6 +319,65 @@ void RendererD3D12::Clear(UINT32 flags)
auto dh = _dSwapChainBuffersRTVs->GetCPUDescriptorHandleForHeapStart();
dh.ptr += _swapChainBufferIndex * _descHandleIncSizeRTV;
static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList()->ClearRenderTargetView(dh, renderer.GetClearColor().ToPointer(), 0, nullptr);
_pCommandLists[_ringBufferIndex]->ClearRenderTargetView(dh, renderer.GetClearColor().ToPointer(), 0, nullptr);
static_cast<CommandBufferD3D12*>(&(*renderer.GetCommandBuffer()))->GetD3DGraphicsCommandList()->OMSetRenderTargets(1, &dh, FALSE, nullptr);
}
void RendererD3D12::WaitIdle()
{
QueueWaitIdle();
}
// Resources:
PBaseCommandBuffer RendererD3D12::InsertCommandBuffer()
{
return TStoreCommandBuffers::Insert();
}
PBaseGeometry RendererD3D12::InsertGeometry()
{
return TStoreGeometry::Insert();
}
PBasePipeline RendererD3D12::InsertPipeline()
{
return TStorePipelines::Insert();
}
PBaseShader RendererD3D12::InsertShader()
{
return TStoreShaders::Insert();
}
PBaseTexture RendererD3D12::InsertTexture()
{
return TStoreTextures::Insert();
}
void RendererD3D12::DeleteCommandBuffer(PBaseCommandBuffer p)
{
TStoreCommandBuffers::Delete(static_cast<PCommandBufferD3D12>(p));
}
void RendererD3D12::DeleteGeometry(PBaseGeometry p)
{
TStoreGeometry::Delete(static_cast<PGeometryD3D12>(p));
}
void RendererD3D12::DeletePipeline(PBasePipeline p)
{
TStorePipelines::Delete(static_cast<PPipelineD3D12>(p));
}
void RendererD3D12::DeleteShader(PBaseShader p)
{
TStoreShaders::Delete(static_cast<PShaderD3D12>(p));
}
void RendererD3D12::DeleteTexture(PBaseTexture p)
{
TStoreTextures::Delete(static_cast<PTextureD3D12>(p));
}

View File

@ -4,7 +4,13 @@ namespace verus
{
namespace CGI
{
class RendererD3D12 : public Singleton<RendererD3D12>, public BaseRenderer
typedef Store<CommandBufferD3D12> TStoreCommandBuffers;
typedef Store<GeometryD3D12> TStoreGeometry;
typedef Store<PipelineD3D12> TStorePipelines;
typedef Store<ShaderD3D12> TStoreShaders;
typedef Store<TextureD3D12> TStoreTextures;
class RendererD3D12 : public Singleton<RendererD3D12>, public BaseRenderer,
private TStoreCommandBuffers, private TStoreGeometry, private TStorePipelines, private TStoreShaders, private TStoreTextures
{
typedef Map<std::thread::id, ComPtr<ID3D12CommandAllocator>> TMapCommandAllocators;
@ -13,8 +19,9 @@ namespace verus
ComPtr<IDXGISwapChain4> _pSwapChain;
Vector<ComPtr<ID3D12Resource>> _vSwapChainBuffers;
ComPtr<ID3D12DescriptorHeap> _dSwapChainBuffersRTVs;
ComPtr<ID3D12Resource> _depthStencilBuffer;
ComPtr<ID3D12DescriptorHeap> _depthStencilBufferView;
TMapCommandAllocators _mapCommandAllocators[s_ringBufferSize];
ComPtr<ID3D12GraphicsCommandList> _pCommandLists[s_ringBufferSize];
ComPtr<ID3D12Fence> _pFence;
HANDLE _hFence = INVALID_HANDLE_VALUE;
UINT64 _nextFenceValue = 1;
@ -40,27 +47,43 @@ namespace verus
void InitD3D();
public:
ComPtr<ID3D12CommandQueue> CreateCommandQueue(D3D12_COMMAND_LIST_TYPE type);
ComPtr<ID3D12CommandAllocator> CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE type);
ComPtr<ID3D12GraphicsCommandList> CreateCommandList(D3D12_COMMAND_LIST_TYPE type, ComPtr<ID3D12CommandAllocator> pCommandAllocator);
ComPtr<ID3D12DescriptorHeap> CreateDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num);
ComPtr<ID3D12Fence> CreateFence();
ComPtr<ID3D12CommandQueue> CreateCommandQueue(D3D12_COMMAND_LIST_TYPE type);
ComPtr<ID3D12CommandAllocator> CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE type);
ComPtr<ID3D12GraphicsCommandList4> CreateCommandList(D3D12_COMMAND_LIST_TYPE type, ComPtr<ID3D12CommandAllocator> pCommandAllocator);
ComPtr<ID3D12DescriptorHeap> CreateDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, UINT num);
ComPtr<ID3D12Fence> CreateFence();
UINT64 QueueSignal();
void WaitForFenceValue(UINT64 value);
void QueueWaitIdle();
static D3D12_RESOURCE_BARRIER MakeResourceBarrierTransition(ID3D12Resource* pResource, D3D12_RESOURCE_STATES before, D3D12_RESOURCE_STATES after);
const ComPtr<ID3D12Device3>& GetDevice() const { return _pDevice; }
ID3D12Device3* GetD3DDevice() const { return _pDevice.Get(); }
ID3D12CommandAllocator* GetD3DCommandAllocator(int ringBufferIndex) const { return _mapCommandAllocators[ringBufferIndex].at(std::this_thread::get_id()).Get(); }
// Which graphics API?
virtual Gapi GetGapi() override { return Gapi::direct3D12; }
// Frame cycle:
virtual void BeginFrame() override;
virtual void EndFrame() override;
virtual void BeginFrame(bool present) override;
virtual void EndFrame(bool present) override;
virtual void Present() override;
virtual void Clear(UINT32 flags) override;
virtual void WaitIdle() override;
// Resources:
virtual PBaseCommandBuffer InsertCommandBuffer() override;
virtual PBaseGeometry InsertGeometry() override;
virtual PBasePipeline InsertPipeline() override;
virtual PBaseShader InsertShader() override;
virtual PBaseTexture InsertTexture() override;
virtual void DeleteCommandBuffer(PBaseCommandBuffer p) override;
virtual void DeleteGeometry(PBaseGeometry p) override;
virtual void DeletePipeline(PBasePipeline p) override;
virtual void DeleteShader(PBaseShader p) override;
virtual void DeleteTexture(PBaseTexture p) override;
};
VERUS_TYPEDEFS(RendererD3D12);
}

View File

@ -12,7 +12,7 @@ HRESULT STDMETHODCALLTYPE ShaderInclude::Open(
LPCVOID* ppData,
UINT* pBytes)
{
const String url = String("<Shaders>/") + pFileName;
const String url = String("[Shaders]:") + pFileName;
Vector<BYTE> vData;
IO::FileSystem::LoadResource(_C(url), vData);
char* p = new char[vData.size()];
@ -47,10 +47,11 @@ void ShaderD3D12::Init(CSZ source, CSZ* branches)
const size_t len = strlen(source);
ShaderInclude inc;
String version = "5_0";
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifndef _DEBUG
flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_OPTIMIZATION_LEVEL3;
String version = "5_1";
#ifdef _DEBUG
const UINT flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS | D3DCOMPILE_OPTIMIZATION_LEVEL1 | D3DCOMPILE_DEBUG;
#else
const UINT flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS | D3DCOMPILE_OPTIMIZATION_LEVEL3;
#endif
ComPtr<ID3DBlob> pErrorMsgs;
@ -105,7 +106,7 @@ void ShaderD3D12::Init(CSZ source, CSZ* branches)
sprintf_s(defWaterQuality, "%d", settings._sceneWaterQuality);
vDefines.push_back({ "_WATER_QUALITY", defWaterQuality });
}
vDefines.push_back({ "_HLSL", "1" });
vDefines.push_back({ "_DIRECT3D", "1" });
const int typeIndex = Utils::Cast32(vDefines.size());
vDefines.push_back({ "_XS", "1" });
vDefines.push_back({});
@ -113,25 +114,45 @@ void ShaderD3D12::Init(CSZ source, CSZ* branches)
Compiled compiled;
vDefines[typeIndex].Name = "_VS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryVS), _C("vs_" + version), flags, 0, &compiled._pBlobs[+Stage::vs], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
if (strstr(source, " mainVS("))
{
compiled._numStages++;
vDefines[typeIndex].Name = "_VS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryVS), _C("vs_" + version), flags, 0, &compiled._pBlobs[+Stage::vs], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
}
vDefines[typeIndex].Name = "_HS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryHS), _C("hs_" + version), flags, 0, &compiled._pBlobs[+Stage::hs], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
if (strstr(source, " mainHS("))
{
compiled._numStages++;
vDefines[typeIndex].Name = "_HS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryHS), _C("hs_" + version), flags, 0, &compiled._pBlobs[+Stage::hs], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
}
vDefines[typeIndex].Name = "_DS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryDS), _C("ds_" + version), flags, 0, &compiled._pBlobs[+Stage::ds], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
if (strstr(source, " mainDS("))
{
compiled._numStages++;
vDefines[typeIndex].Name = "_DS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryDS), _C("ds_" + version), flags, 0, &compiled._pBlobs[+Stage::ds], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
}
vDefines[typeIndex].Name = "_GS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryGS), _C("gs_" + version), flags, 0, &compiled._pBlobs[+Stage::gs], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
if (strstr(source, " mainGS("))
{
compiled._numStages++;
vDefines[typeIndex].Name = "_GS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryGS), _C("gs_" + version), flags, 0, &compiled._pBlobs[+Stage::gs], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
}
vDefines[typeIndex].Name = "_FS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryFS), _C("ps_" + version), flags, 0, &compiled._pBlobs[+Stage::fs], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
if (strstr(source, " mainFS("))
{
compiled._numStages++;
vDefines[typeIndex].Name = "_FS";
hr = D3DCompile(source, len, 0, vDefines.data(), &inc, _C(entryFS), _C("ps_" + version), flags, 0, &compiled._pBlobs[+Stage::fs], &pErrorMsgs);
CheckErrorMsgs(pErrorMsgs);
}
_mapCompiled[entry] = compiled;

View File

@ -22,6 +22,7 @@ namespace verus
struct Compiled
{
ComPtr<ID3DBlob> _pBlobs[+Stage::count];
int _numStages = 0;
};
VERUS_TYPEDEFS(Compiled);
typedef Map<String, Compiled> TMapCompiled;
@ -39,7 +40,8 @@ namespace verus
// D3D12
//
const ComPtr<ID3DBlob>& GetID3DBlob(CSZ branch, Stage stage) const { return _mapCompiled.at(branch)._pBlobs[+stage]; }
ID3DBlob* GetD3DBlob(CSZ branch, Stage stage) const { return _mapCompiled.at(branch)._pBlobs[+stage].Get(); }
int GetNumStages(CSZ branch) const { return _mapCompiled.at(branch)._numStages; }
void OnError(CSZ s);
};

View File

@ -19,7 +19,7 @@ namespace verus
// D3D12
//
ID3D12Resource* GetID3D12Resource() const { return _pResource.Get(); }
ID3D12Resource* GetD3DResource() const { return _pResource.Get(); }
};
VERUS_TYPEDEFS(TextureD3D12);
}

File diff suppressed because it is too large Load Diff

View File

@ -3,4 +3,5 @@
#define VERUS_INCLUDE_D3D12
#include <verus.h>
#include "d3dx12.h"
#include "CGI/CGI.h"

View File

@ -3,12 +3,6 @@
using namespace verus;
using namespace verus::CGI;
VkCommandBuffer CommandBufferVulkan::GetCommandBuffer() const
{
VERUS_QREF_RENDERER;
return _commandBuffers[renderer->GetRingBufferIndex()];
}
CommandBufferVulkan::CommandBufferVulkan()
{
}
@ -21,6 +15,10 @@ CommandBufferVulkan::~CommandBufferVulkan()
void CommandBufferVulkan::Init()
{
VERUS_INIT();
VERUS_QREF_RENDERER_VULKAN;
VERUS_FOR(i, BaseRenderer::s_ringBufferSize)
_commandBuffers[i] = pRendererVulkan->CreateCommandBuffer(pRendererVulkan->GetVkCommandPool(i));
}
void CommandBufferVulkan::Done()
@ -34,81 +32,124 @@ void CommandBufferVulkan::Begin()
VkCommandBufferBeginInfo vkcbbi = {};
vkcbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkcbbi.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
if (VK_SUCCESS != (res = vkBeginCommandBuffer(GetCommandBuffer(), &vkcbbi)))
if (VK_SUCCESS != (res = vkBeginCommandBuffer(GetVkCommandBuffer(), &vkcbbi)))
throw VERUS_RUNTIME_ERROR << "vkBeginCommandBuffer(), res=" << res;
}
void CommandBufferVulkan::End()
{
VkResult res = VK_SUCCESS;
if (VK_SUCCESS != (res = vkEndCommandBuffer(GetCommandBuffer())))
if (VK_SUCCESS != (res = vkEndCommandBuffer(GetVkCommandBuffer())))
throw VERUS_RUNTIME_ERROR << "vkEndCommandBuffer(), res=" << res;
}
void CommandBufferVulkan::BeginRenderPass()
void CommandBufferVulkan::BeginRenderPass(int renderPassID, int framebufferID, std::initializer_list<Vector4> ilClearValues, PcVector4 pRenderArea)
{
VERUS_QREF_RENDERER;
VkClearValue clearValue;
memcpy(&clearValue, renderer.GetClearColor().ToPointer(), sizeof(clearValue));
VERUS_QREF_RENDERER_VULKAN;
VkRenderPassBeginInfo vkrpbi = {};
vkrpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
//vkrpbi.renderPass = renderPass;
//vkrpbi.framebuffer = swapChainFramebuffers[i];
vkrpbi.renderArea.offset = { 0, 0 };
//vkrpbi.renderArea.extent = swapChainExtent;
vkrpbi.clearValueCount = 1;
vkrpbi.pClearValues = &clearValue;
vkCmdBeginRenderPass(GetCommandBuffer(), &vkrpbi, VK_SUBPASS_CONTENTS_INLINE);
vkrpbi.renderPass = pRendererVulkan->GetRenderPassByID(renderPassID);
vkrpbi.framebuffer = pRendererVulkan->GetFramebufferByID(framebufferID);
if (pRenderArea)
{
vkrpbi.renderArea.offset.x = static_cast<int32_t>(pRenderArea->getX());
vkrpbi.renderArea.offset.y = static_cast<int32_t>(pRenderArea->getY());
vkrpbi.renderArea.extent.width = static_cast<uint32_t>(pRenderArea->Width());
vkrpbi.renderArea.extent.height = static_cast<uint32_t>(pRenderArea->Height());
}
VkClearValue clearValue[VERUS_CGI_MAX_RT] = {};
int num = 0;
for (const auto& x : ilClearValues)
{
memcpy(clearValue[num].color.float32, x.ToPointer(), sizeof(clearValue[num].color.float32));
num++;
}
vkrpbi.clearValueCount = num;
vkrpbi.pClearValues = clearValue;
vkCmdBeginRenderPass(GetVkCommandBuffer(), &vkrpbi, VK_SUBPASS_CONTENTS_INLINE);
}
void CommandBufferVulkan::EndRenderPass()
{
vkCmdEndRenderPass(GetCommandBuffer());
vkCmdEndRenderPass(GetVkCommandBuffer());
}
void CommandBufferVulkan::BindVertexBuffers()
void CommandBufferVulkan::BindVertexBuffers(GeometryPtr geo)
{
vkCmdBindVertexBuffers(GetCommandBuffer(), 0, 1, nullptr, nullptr);
auto& geoVulkan = static_cast<RGeometryVulkan>(*geo);
VkBuffer buffers[] = { geoVulkan.GetVkVertexBuffer() };
VkDeviceSize offsets[] = { 0 };
vkCmdBindVertexBuffers(GetVkCommandBuffer(), 0, VERUS_ARRAY_LENGTH(buffers), buffers, offsets);
}
void CommandBufferVulkan::BindIndexBuffer()
void CommandBufferVulkan::BindIndexBuffer(GeometryPtr geo)
{
vkCmdBindIndexBuffer(GetCommandBuffer(), nullptr, 0, VK_INDEX_TYPE_UINT16);
auto& geoVulkan = static_cast<RGeometryVulkan>(*geo);
VkBuffer buffer = geoVulkan.GetVkIndexBuffer();
VkDeviceSize offset = 0;
vkCmdBindIndexBuffer(GetVkCommandBuffer(), buffer, offset, geoVulkan.Has32bitIndices() ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);
}
void CommandBufferVulkan::SetScissor()
void CommandBufferVulkan::SetScissor(std::initializer_list<Vector4> il)
{
vkCmdSetScissor(GetCommandBuffer(), 0, 1, nullptr);
VkRect2D rcVulkan[VERUS_CGI_MAX_RT];
int num = 0;
for (auto& rc : il)
{
rcVulkan[num].offset.x = static_cast<int32_t>(rc.getX());
rcVulkan[num].offset.y = static_cast<int32_t>(rc.getY());
rcVulkan[num].extent.width = static_cast<uint32_t>(rc.Width());
rcVulkan[num].extent.height = static_cast<uint32_t>(rc.Height());
num++;
}
vkCmdSetScissor(GetVkCommandBuffer(), 0, num, rcVulkan);
}
void CommandBufferVulkan::SetViewport()
void CommandBufferVulkan::SetViewport(std::initializer_list<Vector4> il, float minDepth, float maxDepth)
{
vkCmdSetViewport(GetCommandBuffer(), 0, 1, nullptr);
VkViewport vpVulkan[VERUS_CGI_MAX_RT];
int num = 0;
for (auto& rc : il)
{
vpVulkan[num].x = rc.getX();
vpVulkan[num].y = rc.getY();
vpVulkan[num].width = rc.Width();
vpVulkan[num].height = rc.Height();
vpVulkan[num].minDepth = minDepth;
vpVulkan[num].maxDepth = maxDepth;
num++;
}
vkCmdSetViewport(GetVkCommandBuffer(), 0, num, vpVulkan);
}
void CommandBufferVulkan::BindPipeline()
void CommandBufferVulkan::BindPipeline(PipelinePtr pipe)
{
vkCmdBindPipeline(GetCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, nullptr);
auto& pipeVulkan = static_cast<RPipelineVulkan>(*pipe);
vkCmdBindPipeline(GetVkCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeVulkan.GetVkPipeline());
}
void CommandBufferVulkan::PushConstant(PipelinePtr pipe, int offset, int size, const void* p)
{
auto& pipeVulkan = static_cast<RPipelineVulkan>(*pipe);
vkCmdPushConstants(GetVkCommandBuffer(), pipeVulkan.GetVkPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, offset << 2, size << 2, p);
}
void CommandBufferVulkan::PipelineBarrier(TexturePtr tex, ImageLayout oldLayout, ImageLayout newLayout)
{
PTextureVulkan pTex = static_cast<PTextureVulkan>(&(*tex));
auto& texVulkan = static_cast<RTextureVulkan>(*tex);
VkImageMemoryBarrier vkimb = {};
vkimb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
vkimb.oldLayout = ToNativeImageLayout(oldLayout);
vkimb.newLayout = ToNativeImageLayout(newLayout);
vkimb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkimb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkimb.image = pTex->GetVkImage();
vkimb.image = texVulkan.GetVkImage();
vkimb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vkimb.subresourceRange.baseMipLevel = 0;
vkimb.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
vkimb.subresourceRange.baseArrayLayer = 0;
vkimb.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
vkCmdPipelineBarrier(GetCommandBuffer(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkimb);
vkCmdPipelineBarrier(GetVkCommandBuffer(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkimb);
}
void CommandBufferVulkan::Clear(ClearFlags clearFlags)
@ -124,16 +165,22 @@ void CommandBufferVulkan::Clear(ClearFlags clearFlags)
vkisr.levelCount = 1;
vkisr.baseArrayLayer = 0;
vkisr.layerCount = 1;
vkCmdClearColorImage(GetCommandBuffer(), nullptr, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColorValue, 1, &vkisr);
vkCmdClearColorImage(GetVkCommandBuffer(), nullptr, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColorValue, 1, &vkisr);
}
}
void CommandBufferVulkan::Draw()
void CommandBufferVulkan::Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
{
vkCmdDraw(GetCommandBuffer(), 0, 0, 0, 0);
vkCmdDraw(GetVkCommandBuffer(), vertexCount, instanceCount, firstVertex, firstInstance);
}
void CommandBufferVulkan::DrawIndexed()
void CommandBufferVulkan::DrawIndexed(int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance)
{
vkCmdDrawIndexed(GetCommandBuffer(), 0, 0, 0, 0, 0);
vkCmdDrawIndexed(GetVkCommandBuffer(), indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
}
VkCommandBuffer CommandBufferVulkan::GetVkCommandBuffer() const
{
VERUS_QREF_RENDERER;
return _commandBuffers[renderer->GetRingBufferIndex()];
}

View File

@ -6,9 +6,7 @@ namespace verus
{
class CommandBufferVulkan : public BaseCommandBuffer
{
VkCommandBuffer _commandBuffers[BaseRenderer::s_ringBufferSize] = { VK_NULL_HANDLE };
VkCommandBuffer GetCommandBuffer() const;
VkCommandBuffer _commandBuffers[BaseRenderer::s_ringBufferSize] = {};
public:
CommandBufferVulkan();
@ -20,20 +18,28 @@ namespace verus
virtual void Begin() override;
virtual void End() override;
virtual void BeginRenderPass() override;
virtual void BeginRenderPass(int renderPassID, int framebufferID, std::initializer_list<Vector4> ilClearValues, PcVector4 pRenderArea) override;
virtual void EndRenderPass() override;
virtual void BindVertexBuffers() override;
virtual void BindIndexBuffer() override;
virtual void BindVertexBuffers(GeometryPtr geo) override;
virtual void BindIndexBuffer(GeometryPtr geo) override;
virtual void SetScissor() override;
virtual void SetViewport() override;
virtual void SetScissor(std::initializer_list<Vector4> il) override;
virtual void SetViewport(std::initializer_list<Vector4> il, float minDepth, float maxDepth) override;
virtual void BindPipeline() override;
virtual void BindPipeline(PipelinePtr pipe) override;
virtual void PushConstant(PipelinePtr pipe, int offset, int size, const void* p) override;
virtual void PipelineBarrier(TexturePtr tex, ImageLayout oldLayout, ImageLayout newLayout) override;
virtual void Clear(ClearFlags clearFlags) override;
virtual void Draw() override;
virtual void DrawIndexed() override;
virtual void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) override;
virtual void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int vertexOffset, int firstInstance) override;
//
// Vulkan
//
VkCommandBuffer GetVkCommandBuffer() const;
};
VERUS_TYPEDEFS(CommandBufferVulkan);
}

View File

@ -15,9 +15,159 @@ GeometryVulkan::~GeometryVulkan()
void GeometryVulkan::Init(RcGeometryDesc desc)
{
VERUS_INIT();
_32bitIndices = desc._32bitIndices;
_vVertexInputBindingDesc.reserve(GetNumBindings(desc._pInputElementDesc));
_vVertexInputAttributeDesc.reserve(GetNumInputElementDesc(desc._pInputElementDesc));
int i = 0;
while (desc._pInputElementDesc[i]._offset >= 0)
{
int binding = desc._pInputElementDesc[i]._binding;
VkVertexInputRate inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
if (binding < 0)
{
binding = -binding;
_bindingInstMask |= (1 << binding);
inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
}
bool found = false;
for (const auto& x : _vVertexInputBindingDesc)
{
if (x.binding == binding)
{
found = true;
break;
}
}
if (!found)
{
VkVertexInputBindingDescription vkvibd = {};
vkvibd.binding = binding;
vkvibd.stride = desc._pStrides[binding];
vkvibd.inputRate = inputRate;
_vVertexInputBindingDesc.push_back(vkvibd);
}
VkVertexInputAttributeDescription vkviad = {};
vkviad.location = ToNativeLocation(desc._pInputElementDesc[i]._usage, desc._pInputElementDesc[i]._usageIndex);
vkviad.binding = binding;
vkviad.format = ToNativeFormat(desc._pInputElementDesc[i]._usage, desc._pInputElementDesc[i]._type, desc._pInputElementDesc[i]._components);
vkviad.offset = desc._pInputElementDesc[i]._offset;
_vVertexInputAttributeDesc.push_back(vkviad);
i++;
}
_vStrides.reserve(GetNumBindings(desc._pInputElementDesc));
i = 0;
while (desc._pStrides[i] > 0)
{
_vStrides.push_back(desc._pStrides[i]);
i++;
}
}
void GeometryVulkan::Done()
{
VERUS_QREF_RENDERER_VULKAN;
VERUS_VULKAN_DESTROY(_vertexBuffer._buffer, vkDestroyBuffer(pRendererVulkan->GetVkDevice(), _vertexBuffer._buffer, pRendererVulkan->GetAllocator()));
VERUS_VULKAN_DESTROY(_vertexBuffer._deviceMemory, vkFreeMemory(pRendererVulkan->GetVkDevice(), _vertexBuffer._deviceMemory, pRendererVulkan->GetAllocator()));
VERUS_VULKAN_DESTROY(_indexBuffer._buffer, vkDestroyBuffer(pRendererVulkan->GetVkDevice(), _indexBuffer._buffer, pRendererVulkan->GetAllocator()));
VERUS_VULKAN_DESTROY(_indexBuffer._deviceMemory, vkFreeMemory(pRendererVulkan->GetVkDevice(), _indexBuffer._deviceMemory, pRendererVulkan->GetAllocator()));
VERUS_DONE(GeometryVulkan);
}
void GeometryVulkan::BufferDataVB(const void* p, int num, int binding)
{
VERUS_QREF_RENDERER_VULKAN;
VkResult res = VK_SUCCESS;
const int elementSize = _vStrides[binding];
const VkDeviceSize bufferSize = num * elementSize;
CreateBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_stagingVertexBuffer._buffer, _stagingVertexBuffer._deviceMemory);
void* pData = nullptr;
if (VK_SUCCESS != (res = vkMapMemory(pRendererVulkan->GetVkDevice(), _stagingVertexBuffer._deviceMemory, 0, bufferSize, 0, &pData)))
throw VERUS_RECOVERABLE << "vkMapMemory(), res=" << res;
memcpy(pData, p, bufferSize);
vkUnmapMemory(pRendererVulkan->GetVkDevice(), _stagingVertexBuffer._deviceMemory);
CreateBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
_vertexBuffer._buffer, _vertexBuffer._deviceMemory);
CopyBuffer(_stagingVertexBuffer._buffer, _vertexBuffer._buffer, bufferSize);
}
void GeometryVulkan::BufferDataIB(const void* p, int num)
{
VERUS_QREF_RENDERER_VULKAN;
VkResult res = VK_SUCCESS;
const int elementSize = _32bitIndices ? sizeof(UINT32) : sizeof(UINT16);
const VkDeviceSize bufferSize = num * elementSize;
CreateBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
_stagingIndexBuffer._buffer, _stagingIndexBuffer._deviceMemory);
void* pData = nullptr;
if (VK_SUCCESS != (res = vkMapMemory(pRendererVulkan->GetVkDevice(), _stagingIndexBuffer._deviceMemory, 0, bufferSize, 0, &pData)))
throw VERUS_RECOVERABLE << "vkMapMemory(), res=" << res;
memcpy(pData, p, bufferSize);
vkUnmapMemory(pRendererVulkan->GetVkDevice(), _stagingIndexBuffer._deviceMemory);
CreateBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
_indexBuffer._buffer, _indexBuffer._deviceMemory);
CopyBuffer(_stagingIndexBuffer._buffer, _indexBuffer._buffer, bufferSize);
}
void GeometryVulkan::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory)
{
VERUS_QREF_RENDERER_VULKAN;
VkResult res = VK_SUCCESS;
VkBufferCreateInfo vkbci = {};
vkbci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
vkbci.size = size;
vkbci.usage = usage;
vkbci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (VK_SUCCESS != (res = vkCreateBuffer(pRendererVulkan->GetVkDevice(), &vkbci, pRendererVulkan->GetAllocator(), &buffer)))
throw VERUS_RECOVERABLE << "vkCreateBuffer(), res=" << res;
VkMemoryRequirements vkmr = {};
vkGetBufferMemoryRequirements(pRendererVulkan->GetVkDevice(), buffer, &vkmr);
VkMemoryAllocateInfo vkmai = {};
vkmai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
vkmai.allocationSize = vkmr.size;
vkmai.memoryTypeIndex = pRendererVulkan->FindMemoryType(vkmr.memoryTypeBits, properties);
if (VK_SUCCESS != (res = vkAllocateMemory(pRendererVulkan->GetVkDevice(), &vkmai, pRendererVulkan->GetAllocator(), &bufferMemory)))
throw VERUS_RECOVERABLE << "vkAllocateMemory(), res=" << res;
vkBindBufferMemory(pRendererVulkan->GetVkDevice(), buffer, bufferMemory, 0);
}
void GeometryVulkan::CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
{
VERUS_QREF_RENDERER;
auto commandBuffer = static_cast<PCommandBufferVulkan>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
VkBufferCopy copyRegion = {};
copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
}
VkPipelineVertexInputStateCreateInfo GeometryVulkan::GetVkPipelineVertexInputStateCreateInfo() const
{
VkPipelineVertexInputStateCreateInfo vertexInputState = {};
vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputState.vertexBindingDescriptionCount = Utils::Cast32(_vVertexInputBindingDesc.size());
vertexInputState.pVertexBindingDescriptions = _vVertexInputBindingDesc.data();
vertexInputState.vertexAttributeDescriptionCount = Utils::Cast32(_vVertexInputAttributeDesc.size());
vertexInputState.pVertexAttributeDescriptions = _vVertexInputAttributeDesc.data();
return vertexInputState;
}

View File

@ -6,12 +6,41 @@ namespace verus
{
class GeometryVulkan : public BaseGeometry
{
struct VkBufferEx
{
VkBuffer _buffer = VK_NULL_HANDLE;
VkDeviceMemory _deviceMemory = VK_NULL_HANDLE;
};
VkBufferEx _vertexBuffer;
VkBufferEx _indexBuffer;
VkBufferEx _stagingVertexBuffer;
VkBufferEx _stagingIndexBuffer;
Vector<VkVertexInputBindingDescription> _vVertexInputBindingDesc;
Vector<VkVertexInputAttributeDescription> _vVertexInputAttributeDesc;
Vector<int> _vStrides;
public:
GeometryVulkan();
virtual ~GeometryVulkan() override;
virtual void Init(RcGeometryDesc desc) override;
virtual void Done() override;
virtual void BufferDataVB(const void* p, int num, int binding) override;
virtual void BufferDataIB(const void* p, int num) override;
//
// Vulkan
//
void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory);
void CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size);
VkPipelineVertexInputStateCreateInfo GetVkPipelineVertexInputStateCreateInfo() const;
VkBuffer GetVkVertexBuffer() const { return _vertexBuffer._buffer; }
VkBuffer GetVkIndexBuffer() const { return _indexBuffer._buffer; }
};
VERUS_TYPEDEFS(GeometryVulkan);
}

View File

@ -102,3 +102,91 @@ VkSampleCountFlagBits CGI::ToNativeSampleCount(int sampleCount)
default: throw VERUS_RECOVERABLE << "ToNativeSampleCount()";
}
}
int CGI::ToNativeLocation(IeUsage usage, int usageIndex)
{
switch (usage)
{
case IeUsage::position: return 0;
case IeUsage::blendWeight: return 1;
case IeUsage::blendIndices: return 6;
case IeUsage::normal: return 2;
case IeUsage::psize: return 7;
case IeUsage::texCoord: return 8 + usageIndex;
case IeUsage::tangent: return 14;
case IeUsage::binormal: return 15;
case IeUsage::color: return 3 + usageIndex;
default: throw VERUS_RECOVERABLE << "ToNativeLocation()";
}
}
VkFormat CGI::ToNativeFormat(IeUsage usage, IeType type, int components)
{
VERUS_RT_ASSERT(components >= 1 && components <= 4);
int index = components - 1;
static const VkFormat floats[] =
{
VK_FORMAT_R32_SFLOAT,
VK_FORMAT_R32G32_SFLOAT,
VK_FORMAT_R32G32B32_SFLOAT,
VK_FORMAT_R32G32B32A32_SFLOAT
};
static const VkFormat bytes[] =
{
VK_FORMAT_R8G8B8A8_UINT,
VK_FORMAT_R8G8B8A8_UINT,
VK_FORMAT_R8G8B8A8_UINT,
VK_FORMAT_R8G8B8A8_UINT,
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_R8G8B8A8_SNORM,
VK_FORMAT_R8G8B8A8_SNORM,
VK_FORMAT_R8G8B8A8_SNORM,
VK_FORMAT_R8G8B8A8_SNORM
};
static const VkFormat shorts[] =
{
VK_FORMAT_R16G16_SINT,
VK_FORMAT_R16G16_SINT,
VK_FORMAT_R16G16B16A16_SINT,
VK_FORMAT_R16G16B16A16_SINT,
VK_FORMAT_R16G16_SNORM,
VK_FORMAT_R16G16_SNORM,
VK_FORMAT_R16G16B16A16_SNORM,
VK_FORMAT_R16G16B16A16_SNORM
};
switch (type)
{
case IeType::_float:
{
return floats[index];
}
break;
case IeType::_ubyte:
{
VERUS_RT_ASSERT(4 == components);
switch (usage)
{
case IeUsage::normal: index += 8; break; // SNORM.
case IeUsage::color: index += 4; break; // UNORM.
}
return bytes[index];
}
break;
case IeType::_short:
{
VERUS_RT_ASSERT(2 == components || 4 == components);
switch (usage)
{
case IeUsage::tangent:
case IeUsage::binormal:
index += 4; break; // SNORM.
}
return shorts[index];
}
break;
default: throw VERUS_RECOVERABLE << "ToNativeFormat(), IeType=?";
}
}

View File

@ -15,5 +15,8 @@ namespace verus
VkPrimitiveTopology ToNativePrimitiveTopology(PrimitiveTopology primitiveTopology);
VkSampleCountFlagBits ToNativeSampleCount(int sampleCount);
int ToNativeLocation(IeUsage usage, int usageIndex);
VkFormat ToNativeFormat(IeUsage usage, IeType type, int components);
}
}

View File

@ -19,19 +19,24 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
VkResult res = VK_SUCCESS;
CreatePipelineLayout();
CreateRenderPass();
RcGeometryVulkan geo = static_cast<RcGeometryVulkan>(*desc._geometry);
RcShaderVulkan shader = static_cast<RcShaderVulkan>(*desc._shader);
Vector<VkPipelineShaderStageCreateInfo> vShaderStages;
vShaderStages.reserve(5);
RcShaderVulkan shader = static_cast<RcShaderVulkan>(desc._shader);
vShaderStages.reserve(shader.GetNumStages(desc._shaderBranch));
auto PushShaderStage = [&vShaderStages, &shader, &desc](CSZ name, BaseShader::Stage stage, VkShaderStageFlagBits shaderStageFlagBits)
{
VkPipelineShaderStageCreateInfo vkpssci = {};
vkpssci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vkpssci.stage = shaderStageFlagBits;
vkpssci.module = shader.GetVkShaderModule(desc._shaderBranch, stage);
vkpssci.pName = name;
vShaderStages.push_back(vkpssci);
const VkShaderModule shaderModule = shader.GetVkShaderModule(desc._shaderBranch, stage);
if (shaderModule != VK_NULL_HANDLE)
{
VkPipelineShaderStageCreateInfo vkpssci = {};
vkpssci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vkpssci.stage = shaderStageFlagBits;
vkpssci.module = shaderModule;
vkpssci.pName = name;
vShaderStages.push_back(vkpssci);
}
};
PushShaderStage("mainVS", BaseShader::Stage::vs, VK_SHADER_STAGE_VERTEX_BIT);
@ -40,34 +45,17 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
PushShaderStage("mainGS", BaseShader::Stage::gs, VK_SHADER_STAGE_GEOMETRY_BIT);
PushShaderStage("mainFS", BaseShader::Stage::fs, VK_SHADER_STAGE_FRAGMENT_BIT);
VkPipelineVertexInputStateCreateInfo vertexInputState = {};
vertexInputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputState.vertexBindingDescriptionCount = 0;
vertexInputState.vertexAttributeDescriptionCount = 0;
VkPipelineVertexInputStateCreateInfo vertexInputState = geo.GetVkPipelineVertexInputStateCreateInfo();
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = {};
inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAssemblyState.topology = ToNativePrimitiveTopology(desc._topology);
inputAssemblyState.primitiveRestartEnable = desc._primitiveRestartEnable;
VkViewport viewport = {};
viewport.x = desc._viewport.getX();
viewport.y = desc._viewport.getY();
viewport.width = desc._viewport.Width();
viewport.height = desc._viewport.Height();
viewport.minDepth = 0;
viewport.maxDepth = 1;
VkRect2D scissor = {};
scissor.offset.x = static_cast<int32_t>(desc._scissor.getX());
scissor.offset.y = static_cast<int32_t>(desc._scissor.getY());
scissor.extent.width = static_cast<uint32_t>(desc._scissor.Width());
scissor.extent.height = static_cast<uint32_t>(desc._scissor.Height());
VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.viewportCount = 1;
viewportState.pViewports = &viewport;
viewportState.scissorCount = 1;
viewportState.pScissors = &scissor;
VkPipelineRasterizationStateCreateInfo rasterizationState = {};
rasterizationState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
@ -101,6 +89,12 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
colorBlendState.blendConstants[2] = 0;
colorBlendState.blendConstants[3] = 0;
VkDynamicState dynamicStates[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo dynamicState = {};
dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicState.dynamicStateCount = VERUS_ARRAY_LENGTH(dynamicStates);
dynamicState.pDynamicStates = dynamicStates;
VkGraphicsPipelineCreateInfo vkgpci = {};
vkgpci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
vkgpci.stageCount = Utils::Cast32(vShaderStages.size());
@ -111,11 +105,12 @@ void PipelineVulkan::Init(RcPipelineDesc desc)
vkgpci.pRasterizationState = &rasterizationState;
vkgpci.pMultisampleState = &multisampleState;
vkgpci.pColorBlendState = &colorBlendState;
vkgpci.pDynamicState = &dynamicState;
vkgpci.layout = _pipelineLayout;
vkgpci.renderPass = _renderPass;
vkgpci.renderPass = pRendererVulkan->GetRenderPassByID(desc._renderPassID);
vkgpci.subpass = 0;
vkgpci.basePipelineHandle = VK_NULL_HANDLE;
if (VK_SUCCESS != (res = vkCreateGraphicsPipelines(pRendererVulkan->GetDevice(), VK_NULL_HANDLE, 1, &vkgpci, pRendererVulkan->GetAllocator(), &_pipeline)))
if (VK_SUCCESS != (res = vkCreateGraphicsPipelines(pRendererVulkan->GetVkDevice(), VK_NULL_HANDLE, 1, &vkgpci, pRendererVulkan->GetAllocator(), &_pipeline)))
throw VERUS_RUNTIME_ERROR << "vkCreateGraphicsPipelines(), res=" << res;
}
@ -123,9 +118,8 @@ void PipelineVulkan::Done()
{
VERUS_QREF_RENDERER_VULKAN;
VERUS_VULKAN_DESTROY(_pipeline, vkDestroyPipeline(pRendererVulkan->GetDevice(), _pipeline, pRendererVulkan->GetAllocator()));
VERUS_VULKAN_DESTROY(_pipelineLayout, vkDestroyPipelineLayout(pRendererVulkan->GetDevice(), _pipelineLayout, pRendererVulkan->GetAllocator()));
VERUS_VULKAN_DESTROY(_renderPass, vkDestroyRenderPass(pRendererVulkan->GetDevice(), _renderPass, pRendererVulkan->GetAllocator()));
VERUS_VULKAN_DESTROY(_pipeline, vkDestroyPipeline(pRendererVulkan->GetVkDevice(), _pipeline, pRendererVulkan->GetAllocator()));
VERUS_VULKAN_DESTROY(_pipelineLayout, vkDestroyPipelineLayout(pRendererVulkan->GetVkDevice(), _pipelineLayout, pRendererVulkan->GetAllocator()));
VERUS_DONE(PipelineVulkan);
}
@ -134,53 +128,17 @@ void PipelineVulkan::CreatePipelineLayout()
{
VERUS_QREF_RENDERER_VULKAN;
VkResult res = VK_SUCCESS;
VkPushConstantRange vkpcr = {};
vkpcr.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
vkpcr.offset = 0;
vkpcr.size = sizeof(matrix);
VkPipelineLayoutCreateInfo vkplci = {};
vkplci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
vkplci.setLayoutCount = 0;
vkplci.pushConstantRangeCount = 0;
if (VK_SUCCESS != (res = vkCreatePipelineLayout(pRendererVulkan->GetDevice(), &vkplci, pRendererVulkan->GetAllocator(), &_pipelineLayout)))
vkplci.pushConstantRangeCount = 1;
vkplci.pPushConstantRanges = &vkpcr;
if (VK_SUCCESS != (res = vkCreatePipelineLayout(pRendererVulkan->GetVkDevice(), &vkplci, pRendererVulkan->GetAllocator(), &_pipelineLayout)))
throw VERUS_RUNTIME_ERROR << "vkCreatePipelineLayout(), res=" << res;
}
void PipelineVulkan::CreateRenderPass()
{
VERUS_QREF_RENDERER_VULKAN;
VkResult res = VK_SUCCESS;
VkAttachmentDescription attachmentDesc = {};
attachmentDesc.format = VK_FORMAT_B8G8R8A8_UNORM;
attachmentDesc.samples = VK_SAMPLE_COUNT_1_BIT;
attachmentDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachmentDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachmentDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachmentDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachmentDesc.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentReference attachmentRef = {};
attachmentRef.attachment = 0;
attachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &attachmentRef;
VkSubpassDependency dependency = {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
VkRenderPassCreateInfo vkrpci = {};
vkrpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
vkrpci.attachmentCount = 1;
vkrpci.pAttachments = &attachmentDesc;
vkrpci.subpassCount = 1;
vkrpci.pSubpasses = &subpass;
vkrpci.dependencyCount = 1;
vkrpci.pDependencies = &dependency;
if (VK_SUCCESS != (res = vkCreateRenderPass(pRendererVulkan->GetDevice(), &vkrpci, nullptr, &_renderPass)))
throw VERUS_RUNTIME_ERROR << "vkCreateRenderPass(), res=" << res;
}

View File

@ -8,7 +8,6 @@ namespace verus
{
VkPipeline _pipeline = VK_NULL_HANDLE;
VkPipelineLayout _pipelineLayout = VK_NULL_HANDLE;
VkRenderPass _renderPass = VK_NULL_HANDLE;
public:
PipelineVulkan();
@ -17,9 +16,15 @@ namespace verus
virtual void Init(RcPipelineDesc desc) override;
virtual void Done() override;
//
// Vulkan
//
VkPipeline GetVkPipeline() const { return _pipeline; }
VkPipelineLayout GetVkPipelineLayout() const { return _pipelineLayout; }
private:
void CreatePipelineLayout();
void CreateRenderPass();
};
VERUS_TYPEDEFS(PipelineVulkan);
}

View File

@ -57,18 +57,10 @@ void RendererVulkan::Init()
{
VERUS_INIT();
VerusCompilerInit();
_vRenderPasses.reserve(20);
_vFramebuffers.reserve(40);
const char* defines[] =
{
"Foo", "1",
"Bar", "2",
nullptr
};
UINT32* pCode;
UINT32 size;
const char* pErrorMsg;
VerusCompile("float4 mainVS() : POSITION {return float4(0, 0, 0, 1);}", defines, "mainVS", "vs", 0, &pCode, &size, &pErrorMsg);
VerusCompilerInit();
CreateInstance();
#if defined(_DEBUG) || defined(VERUS_DEBUG)
@ -80,17 +72,14 @@ void RendererVulkan::Init()
CreateSwapChain();
CreateImageViews();
CreateCommandPools();
CreateCommandBuffers();
CreateSyncObjects();
CreateRenderPass("Master", { RP::Attachment("RT", Format::unormR8G8B8A8).LoadOpClear().FinalLayout(ImageLayout::presentSrc) }, { RP::Subpass("SP") }, {});
}
void RendererVulkan::Done()
{
if (_device)
vkDeviceWaitIdle(_device);
WaitIdle();
DeleteFramebuffer(-1);
DeleteRenderPass(-1);
VERUS_FOR(i, s_ringBufferSize)
{
VERUS_VULKAN_DESTROY(_acquireNextImageSemaphores[i], vkDestroySemaphore(_device, _acquireNextImageSemaphores[i], GetAllocator()));
@ -142,16 +131,17 @@ void RendererVulkan::VerusCompilerDone()
#endif
}
bool RendererVulkan::VerusCompile(CSZ source, CSZ* defines, CSZ entryPoint, CSZ target, UINT32 flags, UINT32** ppCode, UINT32* pSize, CSZ* ppErrorMsgs)
bool RendererVulkan::VerusCompile(CSZ source, CSZ* defines, BaseShaderInclude* pInclude,
CSZ entryPoint, CSZ target, UINT32 flags, UINT32** ppCode, UINT32* pSize, CSZ* ppErrorMsgs)
{
#ifdef _WIN32
PFNVERUSCOMPILE VerusCompile = reinterpret_cast<PFNVERUSCOMPILE>(
GetProcAddress(LoadLibraryA("VulkanShaderCompiler.dll"), "VerusCompile"));
return VerusCompile(source, defines, entryPoint, target, flags, ppCode, pSize, ppErrorMsgs);
return VerusCompile(source, defines, pInclude, entryPoint, target, flags, ppCode, pSize, ppErrorMsgs);
#else
PFNVERUSCOMPILE VerusCompile = reinterpret_cast<VerusCompile>(
dlsym(dlopen("./libVulkanShaderCompiler.so", RTLD_LAZY), "VerusCompile"));
return VerusCompile(source, defines, entryPoint, target, flags, ppCode, pSize, ppErrorMsgs);
return VerusCompile(source, defines, pInclude, entryPoint, target, flags, ppCode, pSize, ppErrorMsgs);
#endif
}
@ -500,21 +490,6 @@ void RendererVulkan::CreateCommandPools()
}
}
void RendererVulkan::CreateCommandBuffers()
{
VkResult res = VK_SUCCESS;
VERUS_FOR(i, s_ringBufferSize)
{
VkCommandBufferAllocateInfo vkcbai = {};
vkcbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
vkcbai.commandPool = _commandPools[i];
vkcbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
vkcbai.commandBufferCount = 1;
if (VK_SUCCESS != (res = vkAllocateCommandBuffers(_device, &vkcbai, &_commandBuffers[i])))
throw VERUS_RUNTIME_ERROR << "vkAllocateCommandBuffers(), res=" << res;
}
}
void RendererVulkan::CreateSyncObjects()
{
VkResult res = VK_SUCCESS;
@ -534,90 +509,93 @@ void RendererVulkan::CreateSyncObjects()
}
}
void RendererVulkan::BeginFrame()
VkCommandBuffer RendererVulkan::CreateCommandBuffer(VkCommandPool commandPool)
{
VkResult res = VK_SUCCESS;
VkCommandBufferAllocateInfo vkcbai = {};
vkcbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
vkcbai.commandPool = commandPool;
vkcbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
vkcbai.commandBufferCount = 1;
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
if (VK_SUCCESS != (res = vkAllocateCommandBuffers(_device, &vkcbai, &commandBuffer)))
throw VERUS_RUNTIME_ERROR << "vkAllocateCommandBuffers(), res=" << res;
return commandBuffer;
}
void RendererVulkan::BeginFrame(bool present)
{
VERUS_QREF_RENDERER;
VkResult res = VK_SUCCESS;
if (VK_SUCCESS != (res = vkWaitForFences(_device, 1, &_queueSubmitFences[_ringBufferIndex], VK_TRUE, UINT64_MAX)))
throw VERUS_RUNTIME_ERROR << "vkWaitForFences(), res=" << res;
if (VK_SUCCESS != (res = vkResetFences(_device, 1, &_queueSubmitFences[_ringBufferIndex])))
throw VERUS_RUNTIME_ERROR << "vkResetFences(), res=" << res;
if (VK_SUCCESS != (res = vkAcquireNextImageKHR(_device, _swapChain, UINT64_MAX, _acquireNextImageSemaphores[_ringBufferIndex], VK_NULL_HANDLE, &_swapChainBufferIndex)))
throw VERUS_RUNTIME_ERROR << "vkAcquireNextImageKHR(), res=" << res;
if (present)
{
if (VK_SUCCESS != (res = vkAcquireNextImageKHR(_device, _swapChain, UINT64_MAX, _acquireNextImageSemaphores[_ringBufferIndex], VK_NULL_HANDLE, &_swapChainBufferIndex)))
throw VERUS_RUNTIME_ERROR << "vkAcquireNextImageKHR(), res=" << res;
}
if (VK_SUCCESS != (res = vkResetCommandPool(_device, _commandPools[_ringBufferIndex], VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT)))
throw VERUS_RUNTIME_ERROR << "vkResetCommandPool(), res=" << res;
VkCommandBufferBeginInfo vkcbbi = {};
vkcbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkcbbi.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
if (VK_SUCCESS != (res = vkBeginCommandBuffer(_commandBuffers[_ringBufferIndex], &vkcbbi)))
throw VERUS_RUNTIME_ERROR << "vkBeginCommandBuffer(), res=" << res;
renderer.GetCommandBuffer()->Begin();
}
void RendererVulkan::EndFrame()
void RendererVulkan::EndFrame(bool present)
{
VERUS_QREF_RENDERER;
VkResult res = VK_SUCCESS;
VkImageMemoryBarrier vkimb = {};
vkimb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
vkimb.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
vkimb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
vkimb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkimb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkimb.image = _vSwapChainImages[_swapChainBufferIndex];
vkimb.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vkimb.subresourceRange.baseMipLevel = 0;
vkimb.subresourceRange.levelCount = 1;
vkimb.subresourceRange.baseArrayLayer = 0;
vkimb.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(_commandBuffers[_ringBufferIndex], VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkimb);
if (VK_SUCCESS != (res = vkEndCommandBuffer(_commandBuffers[_ringBufferIndex])))
throw VERUS_RUNTIME_ERROR << "vkEndCommandBuffer(), res=" << res;
renderer.GetCommandBuffer()->End();
const VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
const VkSemaphore waitSemaphores[] = { _acquireNextImageSemaphores[_ringBufferIndex] };
const VkSemaphore signalSemaphores[] = { _queueSubmitSemaphores[_ringBufferIndex] };
_acquireNextImageSemaphore = _acquireNextImageSemaphores[_ringBufferIndex];
_queueSubmitSemaphore = _queueSubmitSemaphores[_ringBufferIndex];
VkCommandBuffer commandBuffer = static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer();
VkSubmitInfo vksi = {};
vksi.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
vksi.waitSemaphoreCount = VERUS_ARRAY_LENGTH(waitSemaphores);
vksi.pWaitSemaphores = waitSemaphores;
vksi.pWaitDstStageMask = waitStages;
if (present)
{
vksi.waitSemaphoreCount = 1;
vksi.pWaitSemaphores = &_acquireNextImageSemaphore;
vksi.pWaitDstStageMask = waitStages;
}
vksi.commandBufferCount = 1;
vksi.pCommandBuffers = &_commandBuffers[_ringBufferIndex];
vksi.pCommandBuffers = &commandBuffer;
if (!_queueFamilyIndices.IsSameQueue())
{
vksi.signalSemaphoreCount = VERUS_ARRAY_LENGTH(signalSemaphores);
vksi.pSignalSemaphores = signalSemaphores;
vksi.signalSemaphoreCount = 1;
vksi.pSignalSemaphores = &_queueSubmitSemaphore;
}
if (VK_SUCCESS != (res = vkQueueSubmit(_graphicsQueue, 1, &vksi, _queueSubmitFences[_ringBufferIndex])))
throw VERUS_RUNTIME_ERROR << "vkQueueSubmit(), res=" << res;
_ringBufferIndex = (_ringBufferIndex + 1) % s_ringBufferSize;
}
void RendererVulkan::Present()
{
VkResult res = VK_SUCCESS;
const VkSemaphore waitSemaphores[] = { _queueSubmitSemaphores[_ringBufferIndex] };
const VkSwapchainKHR swapChains[] = { _swapChain };
VkPresentInfoKHR vkpi = {};
vkpi.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
if (!_queueFamilyIndices.IsSameQueue())
{
vkpi.waitSemaphoreCount = VERUS_ARRAY_LENGTH(waitSemaphores);
vkpi.pWaitSemaphores = waitSemaphores;
vkpi.waitSemaphoreCount = 1;
vkpi.pWaitSemaphores = &_queueSubmitSemaphore;
}
vkpi.swapchainCount = VERUS_ARRAY_LENGTH(swapChains);
vkpi.pSwapchains = swapChains;
vkpi.pImageIndices = &_swapChainBufferIndex;
if (VK_SUCCESS != (res = vkQueuePresentKHR(_presentQueue, &vkpi)))
throw VERUS_RUNTIME_ERROR << "vkQueuePresentKHR(), res=" << res;
_ringBufferIndex = (_ringBufferIndex + 1) % s_ringBufferSize;
}
void RendererVulkan::Clear(UINT32 flags)
@ -636,7 +614,8 @@ void RendererVulkan::Clear(UINT32 flags)
vkimb.subresourceRange.levelCount = 1;
vkimb.subresourceRange.baseArrayLayer = 0;
vkimb.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(_commandBuffers[_ringBufferIndex], VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkimb);
vkCmdPipelineBarrier(static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer(),
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &vkimb);
VkClearColorValue clearColorValue;
memcpy(&clearColorValue, renderer.GetClearColor().ToPointer(), sizeof(clearColorValue));
@ -646,33 +625,352 @@ void RendererVulkan::Clear(UINT32 flags)
vkisr.levelCount = 1;
vkisr.baseArrayLayer = 0;
vkisr.layerCount = 1;
vkCmdClearColorImage(_commandBuffers[_ringBufferIndex], _vSwapChainImages[_swapChainBufferIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColorValue, 1, &vkisr);
vkCmdClearColorImage(static_cast<CommandBufferVulkan*>(&(*renderer.GetCommandBuffer()))->GetVkCommandBuffer(),
_vSwapChainImages[_swapChainBufferIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColorValue, 1, &vkisr);
}
void RendererVulkan::CreateRenderPass(CSZ name, std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD)
void RendererVulkan::WaitIdle()
{
Vector<VkAttachmentDescription> vAttachmentDescription;
vAttachmentDescription.reserve(ilA.size());
for (auto attachment : ilA)
if (_device)
vkDeviceWaitIdle(_device);
}
// Resources:
PBaseCommandBuffer RendererVulkan::InsertCommandBuffer()
{
return TStoreCommandBuffers::Insert();
}
PBaseGeometry RendererVulkan::InsertGeometry()
{
return TStoreGeometry::Insert();
}
PBasePipeline RendererVulkan::InsertPipeline()
{
return TStorePipelines::Insert();
}
PBaseShader RendererVulkan::InsertShader()
{
return TStoreShaders::Insert();
}
PBaseTexture RendererVulkan::InsertTexture()
{
return TStoreTextures::Insert();
}
void RendererVulkan::DeleteCommandBuffer(PBaseCommandBuffer p)
{
TStoreCommandBuffers::Delete(static_cast<PCommandBufferVulkan>(p));
}
void RendererVulkan::DeleteGeometry(PBaseGeometry p)
{
TStoreGeometry::Delete(static_cast<PGeometryVulkan>(p));
}
void RendererVulkan::DeletePipeline(PBasePipeline p)
{
TStorePipelines::Delete(static_cast<PPipelineVulkan>(p));
}
void RendererVulkan::DeleteShader(PBaseShader p)
{
TStoreShaders::Delete(static_cast<PShaderVulkan>(p));
}
void RendererVulkan::DeleteTexture(PBaseTexture p)
{
TStoreTextures::Delete(static_cast<PTextureVulkan>(p));
}
int RendererVulkan::CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD)
{
VkResult res = VK_SUCCESS;
auto ToNativeLoadOp = [](RP::Attachment::LoadOp op)
{
switch (op)
{
case RP::Attachment::LoadOp::load: return VK_ATTACHMENT_LOAD_OP_LOAD;
case RP::Attachment::LoadOp::clear: return VK_ATTACHMENT_LOAD_OP_CLEAR;
case RP::Attachment::LoadOp::dontCare: return VK_ATTACHMENT_LOAD_OP_DONT_CARE;
default: throw VERUS_RECOVERABLE << "CreateRenderPass(), LoadOp";
};
};
auto ToNativeStoreOp = [](RP::Attachment::StoreOp op)
{
switch (op)
{
case RP::Attachment::StoreOp::store: return VK_ATTACHMENT_STORE_OP_STORE;
case RP::Attachment::StoreOp::dontCare: return VK_ATTACHMENT_STORE_OP_DONT_CARE;
default: throw VERUS_RECOVERABLE << "CreateRenderPass(), StoreOp";
}
};
Vector<VkAttachmentDescription> vAttachmentDesc;
vAttachmentDesc.reserve(ilA.size());
for (auto& attachment : ilA)
{
VkAttachmentDescription vkad = {};
vkad.format = ToNativeFormat(attachment._format);
vkad.samples = ToNativeSampleCount(attachment._sampleCount);
switch (attachment._loadOp)
{
case RP::Attachment::LoadOp::load: vkad.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; break;
case RP::Attachment::LoadOp::clear: vkad.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; break;
case RP::Attachment::LoadOp::dontCare: vkad.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; break;
default: throw VERUS_RECOVERABLE << "CreateRenderPass(), LoadOp";
};
switch (attachment._storeOp)
{
case RP::Attachment::StoreOp::store: vkad.storeOp = VK_ATTACHMENT_STORE_OP_STORE; break;
case RP::Attachment::StoreOp::dontCare: vkad.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; break;
default: throw VERUS_RECOVERABLE << "CreateRenderPass(), StoreOp";
}
vkad.loadOp = ToNativeLoadOp(attachment._loadOp);
vkad.storeOp = ToNativeStoreOp(attachment._storeOp);
vkad.stencilLoadOp = ToNativeLoadOp(attachment._stencilLoadOp);
vkad.stencilStoreOp = ToNativeStoreOp(attachment._stencilStoreOp);
vkad.initialLayout = ToNativeImageLayout(attachment._initialLayout);
vkad.finalLayout = ToNativeImageLayout(attachment._finalLayout);
vAttachmentDescription.push_back(vkad);
vAttachmentDesc.push_back(vkad);
}
auto GetAttachmentIndexByName = [&ilA](CSZ name) -> uint32_t
{
if (!name)
return VK_ATTACHMENT_UNUSED;
uint32_t index = 0;
for (auto& attachment : ilA)
{
if (!strcmp(attachment._name, name))
return index;
index++;
}
throw VERUS_RECOVERABLE << "CreateRenderPass(), Attachment not found";
};
struct SubpassMetadata
{
int inputRefIndex = -1;
int colorRefIndex = -1;
int resolveRefIndex = -1;
int depthStencilRefIndex = -1;
int preserveIndex = -1;
};
Vector<VkAttachmentReference> vAttachmentRef;
vAttachmentRef.reserve(20);
Vector<uint32_t> vAttachmentIndex;
vAttachmentIndex.reserve(20);
Vector<SubpassMetadata> vSubpassMetadata;
vSubpassMetadata.reserve(ilS.size());
Vector<VkSubpassDescription> vSubpassDesc;
vSubpassDesc.reserve(ilS.size());
for (auto& subpass : ilS)
{
SubpassMetadata subpassMetadata;
VkSubpassDescription vksd = {};
vksd.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
vksd.inputAttachmentCount = Utils::Cast32(subpass._ilInput.size());
subpassMetadata.inputRefIndex = Utils::Cast32(vAttachmentRef.size());
for (auto& input : subpass._ilInput)
{
VkAttachmentReference vkar = {};
vkar.attachment = GetAttachmentIndexByName(input._name);
vkar.layout = ToNativeImageLayout(input._layout);
vAttachmentRef.push_back(vkar);
}
vksd.colorAttachmentCount = Utils::Cast32(subpass._ilColor.size());
subpassMetadata.colorRefIndex = Utils::Cast32(vAttachmentRef.size());
for (auto& color : subpass._ilColor)
{
VkAttachmentReference vkar = {};
vkar.attachment = GetAttachmentIndexByName(color._name);
vkar.layout = ToNativeImageLayout(color._layout);
vAttachmentRef.push_back(vkar);
}
if (subpass._depthStencil._name)
{
subpassMetadata.depthStencilRefIndex = Utils::Cast32(vAttachmentRef.size());
VkAttachmentReference vkar = {};
vkar.attachment = GetAttachmentIndexByName(subpass._depthStencil._name);
vkar.layout = ToNativeImageLayout(subpass._depthStencil._layout);
vAttachmentRef.push_back(vkar);
}
vksd.preserveAttachmentCount = Utils::Cast32(subpass._ilPreserve.size());
subpassMetadata.preserveIndex = Utils::Cast32(vAttachmentIndex.size());
for (auto& preserve : subpass._ilPreserve)
{
const uint32_t index = GetAttachmentIndexByName(preserve._name);
vAttachmentIndex.push_back(index);
}
vSubpassDesc.push_back(vksd);
vSubpassMetadata.push_back(subpassMetadata);
}
// vAttachmentRef is ready, convert indices to actual pointers:
if (vAttachmentRef.empty())
throw VERUS_RECOVERABLE << "CreateRenderPass(), No attachment references";
int index = 0;
for (auto& sd : vSubpassDesc)
{
const SubpassMetadata& sm = vSubpassMetadata[index];
if (sd.inputAttachmentCount)
sd.pInputAttachments = &vAttachmentRef[sm.inputRefIndex];
if (sd.colorAttachmentCount)
sd.pColorAttachments = &vAttachmentRef[sm.colorRefIndex];
if (sm.depthStencilRefIndex >= 0)
sd.pDepthStencilAttachment = &vAttachmentRef[sm.depthStencilRefIndex];
if (sd.preserveAttachmentCount)
sd.pPreserveAttachments = &vAttachmentIndex[sm.preserveIndex];
index++;
}
Vector<VkSubpassDependency> vSubpassDependency;
vSubpassDependency.reserve(ilD.size());
for (auto& dependency : ilD)
{
VkSubpassDependency vksd = {};
vSubpassDependency.push_back(vksd);
}
VkSubpassDependency dependency = {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
vSubpassDependency.push_back(dependency);
VkRenderPass renderPass = VK_NULL_HANDLE;
VkRenderPassCreateInfo vkrpci = {};
vkrpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
vkrpci.attachmentCount = Utils::Cast32(vAttachmentDesc.size());
vkrpci.pAttachments = vAttachmentDesc.data();
vkrpci.subpassCount = Utils::Cast32(vSubpassDesc.size());
vkrpci.pSubpasses = vSubpassDesc.data();
vkrpci.dependencyCount = Utils::Cast32(vSubpassDependency.size());
vkrpci.pDependencies = vSubpassDependency.data();
if (VK_SUCCESS != (res = vkCreateRenderPass(_device, &vkrpci, GetAllocator(), &renderPass)))
throw VERUS_RUNTIME_ERROR << "vkCreateRenderPass(), res=" << res;
const int id = GetNextRenderPassID();
if (id >= _vRenderPasses.size())
_vRenderPasses.push_back(renderPass);
else
_vRenderPasses[id] = renderPass;
return id;
}
int RendererVulkan::CreateFramebuffer(int renderPassID, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex)
{
VkResult res = VK_SUCCESS;
VkImageView imageViews[VERUS_CGI_MAX_RT] = {};
VkFramebuffer framebuffer = VK_NULL_HANDLE;
VkFramebufferCreateInfo vkfci = {};
vkfci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
vkfci.renderPass = GetRenderPassByID(renderPassID);
int num = 0;
if (swapChainBufferIndex >= 0)
{
imageViews[num] = _vSwapChainImageViews[swapChainBufferIndex];
num++;
}
for (const auto& x : il)
{
auto& texVulkan = static_cast<RTextureVulkan>(*x);
imageViews[num] = texVulkan.GetVkImageView();
num++;
}
vkfci.attachmentCount = num;
vkfci.pAttachments = imageViews;
vkfci.width = w;
vkfci.height = h;
vkfci.layers = 1;
if (VK_SUCCESS != (res = vkCreateFramebuffer(_device, &vkfci, GetAllocator(), &framebuffer)))
throw VERUS_RUNTIME_ERROR << "vkCreateFramebuffer(), res=" << res;
const int id = GetNextFramebufferID();
if (id >= _vFramebuffers.size())
_vFramebuffers.push_back(framebuffer);
else
_vFramebuffers[id] = framebuffer;
return id;
}
void RendererVulkan::DeleteRenderPass(int id)
{
if (id >= 0)
{
vkDestroyRenderPass(_device, _vRenderPasses[id], GetAllocator());
_vRenderPasses[id] = VK_NULL_HANDLE;
}
else
{
for (auto renderPass : _vRenderPasses)
vkDestroyRenderPass(_device, renderPass, GetAllocator());
_vRenderPasses.clear();
}
}
void RendererVulkan::DeleteFramebuffer(int id)
{
if (id >= 0)
{
vkDestroyFramebuffer(_device, _vFramebuffers[id], GetAllocator());
_vFramebuffers[id] = VK_NULL_HANDLE;
}
else
{
for (auto framebuffer : _vFramebuffers)
vkDestroyFramebuffer(_device, framebuffer, GetAllocator());
_vFramebuffers.clear();
}
}
int RendererVulkan::GetNextRenderPassID() const
{
const int num = Utils::Cast32(_vRenderPasses.size());
VERUS_FOR(i, num)
{
if (VK_NULL_HANDLE == _vRenderPasses[i])
return i;
}
return num;
}
int RendererVulkan::GetNextFramebufferID() const
{
const int num = Utils::Cast32(_vFramebuffers.size());
VERUS_FOR(i, num)
{
if (VK_NULL_HANDLE == _vFramebuffers[i])
return i;
}
return num;
}
VkRenderPass RendererVulkan::GetRenderPassByID(int id) const
{
return _vRenderPasses[id];
}
VkFramebuffer RendererVulkan::GetFramebufferByID(int id) const
{
return _vFramebuffers[id];
}
uint32_t RendererVulkan::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
{
VkPhysicalDeviceMemoryProperties vkpdmp = {};
vkGetPhysicalDeviceMemoryProperties(_physicalDevice, &vkpdmp);
for (uint32_t i = 0; i < vkpdmp.memoryTypeCount; i++)
{
if ((typeFilter & (1 << i)) && (vkpdmp.memoryTypes[i].propertyFlags & properties) == properties)
return i;
}
throw VERUS_RECOVERABLE << "FindMemoryType(), Memory type not found";
}

View File

@ -4,7 +4,19 @@ namespace verus
{
namespace CGI
{
class RendererVulkan : public Singleton<RendererVulkan>, public BaseRenderer
struct BaseShaderInclude
{
virtual void Open(CSZ filename, void** ppData, UINT32* pBytes) = 0;
virtual void Close(void* pData) = 0;
};
typedef Store<CommandBufferVulkan> TStoreCommandBuffers;
typedef Store<GeometryVulkan> TStoreGeometry;
typedef Store<PipelineVulkan> TStorePipelines;
typedef Store<ShaderVulkan> TStoreShaders;
typedef Store<TextureVulkan> TStoreTextures;
class RendererVulkan : public Singleton<RendererVulkan>, public BaseRenderer,
private TStoreCommandBuffers, private TStoreGeometry, private TStorePipelines, private TStoreShaders, private TStoreTextures
{
struct QueueFamilyIndices
{
@ -44,13 +56,15 @@ namespace verus
VkSwapchainKHR _swapChain = VK_NULL_HANDLE;
Vector<VkImage> _vSwapChainImages;
Vector<VkImageView> _vSwapChainImageViews;
VkCommandPool _commandPools[s_ringBufferSize] = { VK_NULL_HANDLE };
VkCommandBuffer _commandBuffers[s_ringBufferSize] = { VK_NULL_HANDLE };
VkSemaphore _acquireNextImageSemaphores[s_ringBufferSize] = { VK_NULL_HANDLE };
VkSemaphore _queueSubmitSemaphores[s_ringBufferSize] = { VK_NULL_HANDLE };
VkFence _queueSubmitFences[s_ringBufferSize] = { VK_NULL_HANDLE };
VkCommandPool _commandPools[s_ringBufferSize] = {};
VkSemaphore _acquireNextImageSemaphores[s_ringBufferSize] = {};
VkSemaphore _queueSubmitSemaphores[s_ringBufferSize] = {};
VkSemaphore _acquireNextImageSemaphore = VK_NULL_HANDLE;
VkSemaphore _queueSubmitSemaphore = VK_NULL_HANDLE;
VkFence _queueSubmitFences[s_ringBufferSize] = {};
QueueFamilyIndices _queueFamilyIndices;
TMapRenderPasses _mapRenderPasses;
Vector<VkRenderPass> _vRenderPasses;
Vector<VkFramebuffer> _vFramebuffers;
public:
RendererVulkan();
@ -63,7 +77,8 @@ namespace verus
static void VerusCompilerInit();
static void VerusCompilerDone();
static bool VerusCompile(CSZ source, CSZ* defines, CSZ entryPoint, CSZ target, UINT32 flags, UINT32** ppCode, UINT32* pSize, CSZ* ppErrorMsgs);
static bool VerusCompile(CSZ source, CSZ* defines, BaseShaderInclude* pInclude,
CSZ entryPoint, CSZ target, UINT32 flags, UINT32** ppCode, UINT32* pSize, CSZ* ppErrorMsgs);
private:
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsMessengerCallback(
@ -85,36 +100,49 @@ namespace verus
void CreateSwapChain();
void CreateImageViews();
void CreateCommandPools();
void CreateCommandBuffers();
void CreateSyncObjects();
public:
VkDevice GetDevice() const { return _device; }
VkCommandBuffer CreateCommandBuffer(VkCommandPool commandPool);
VkDevice GetVkDevice() const { return _device; }
const VkAllocationCallbacks* GetAllocator() const { return nullptr; }
VkCommandPool GetVkCommandPool(int ringBufferIndex) const { return _commandPools[ringBufferIndex]; }
// Which graphics API?
virtual Gapi GetGapi() override { return Gapi::vulkan; }
// Frame cycle:
virtual void BeginFrame() override;
virtual void EndFrame() override;
virtual void BeginFrame(bool present) override;
virtual void EndFrame(bool present) override;
virtual void Present() override;
virtual void Clear(UINT32 flags) override;
virtual void WaitIdle() override;
// Resources:
virtual PBaseCommandBuffer InsertCommandBuffer() override { return nullptr; }
virtual PBaseGeometry InsertGeometry() override { return nullptr; }
virtual PBasePipeline InsertPipeline() override { return nullptr; }
virtual PBaseShader InsertShader() override { return nullptr; }
virtual PBaseTexture InsertTexture() override { return nullptr; }
virtual PBaseCommandBuffer InsertCommandBuffer() override;
virtual PBaseGeometry InsertGeometry() override;
virtual PBasePipeline InsertPipeline() override;
virtual PBaseShader InsertShader() override;
virtual PBaseTexture InsertTexture() override;
virtual void DeleteCommandBuffer(PBaseCommandBuffer p) override {}
virtual void DeleteGeometry(PBaseGeometry p) override {}
virtual void DeletePipeline(PBasePipeline p) override {}
virtual void DeleteShader(PBaseShader p) override {}
virtual void DeleteTexture(PBaseTexture p) override {}
virtual void DeleteCommandBuffer(PBaseCommandBuffer p) override;
virtual void DeleteGeometry(PBaseGeometry p) override;
virtual void DeletePipeline(PBasePipeline p) override;
virtual void DeleteShader(PBaseShader p) override;
virtual void DeleteTexture(PBaseTexture p) override;
void CreateRenderPass(CSZ name, std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD);
virtual int CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD) override;
virtual int CreateFramebuffer(int renderPassID, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex) override;
virtual void DeleteRenderPass(int id) override;
virtual void DeleteFramebuffer(int id) override;
int GetNextRenderPassID() const;
int GetNextFramebufferID() const;
VkRenderPass GetRenderPassByID(int id) const;
VkFramebuffer GetFramebufferByID(int id) const;
uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
};
VERUS_TYPEDEFS(RendererVulkan);
}
@ -123,7 +151,8 @@ namespace verus
{
typedef void(*PFNVERUSCOMPILERINIT)();
typedef void(*PFNVERUSCOMPILERDONE)();
typedef bool(*PFNVERUSCOMPILE)(CSZ source, CSZ* defines, CSZ entryPoint, CSZ target, UINT32 flags, UINT32** ppCode, UINT32* pSize, CSZ* ppErrorMsgs);
typedef bool(*PFNVERUSCOMPILE)(CSZ source, CSZ* defines, CGI::BaseShaderInclude* pInclude,
CSZ entryPoint, CSZ target, UINT32 flags, UINT32** ppCode, UINT32* pSize, CSZ* ppErrorMsgs);
}
}

View File

@ -3,6 +3,27 @@
using namespace verus;
using namespace verus::CGI;
struct ShaderInclude : BaseShaderInclude
{
virtual void Open(CSZ filename, void** ppData, UINT32* pBytes) override
{
const String url = String("[Shaders]:") + filename;
Vector<BYTE> vData;
IO::FileSystem::LoadResource(_C(url), vData);
char* p = new char[vData.size()];
memcpy(p, vData.data(), vData.size());
*pBytes = Utils::Cast32(vData.size());
*ppData = p;
}
virtual void Close(void* pData) override
{
delete[] pData;
}
};
// ShaderVulkan:
ShaderVulkan::ShaderVulkan()
{
}
@ -17,6 +38,12 @@ void ShaderVulkan::Init(CSZ source, CSZ* branches)
VERUS_INIT();
VERUS_QREF_CONST_SETTINGS;
ShaderInclude inc;
#ifdef _DEBUG
const UINT32 flags = 1;
#else
const UINT32 flags = 0;
#endif
UINT32* pCode = nullptr;
UINT32 size = 0;
CSZ pErrorMsgs = nullptr;
@ -29,13 +56,15 @@ void ShaderVulkan::Init(CSZ source, CSZ* branches)
auto CreateShaderModule = [](const UINT32* pCode, UINT32 size, VkShaderModule& shaderModule)
{
if (!pCode || !size)
return;
VERUS_QREF_RENDERER_VULKAN;
VkResult res = VK_SUCCESS;
VkShaderModuleCreateInfo vksmci = {};
vksmci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
vksmci.codeSize = size;
vksmci.pCode = pCode;
if (VK_SUCCESS != (res = vkCreateShaderModule(pRendererVulkan->GetDevice(), &vksmci, pRendererVulkan->GetAllocator(), &shaderModule)))
if (VK_SUCCESS != (res = vkCreateShaderModule(pRendererVulkan->GetVkDevice(), &vksmci, pRendererVulkan->GetAllocator(), &shaderModule)))
throw VERUS_RUNTIME_ERROR << "vkCreateShaderModule(), res=" << res;
};
@ -92,30 +121,50 @@ void ShaderVulkan::Init(CSZ source, CSZ* branches)
Compiled compiled;
vDefines[typeIndex] = "_VS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), _C(entryVS), "vs", 0, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::vs]);
if (strstr(source, " mainVS("))
{
compiled._numStages++;
vDefines[typeIndex] = "_VS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), &inc, _C(entryVS), "vs", flags, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::vs]);
}
vDefines[typeIndex] = "_HS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), _C(entryHS), "hs", 0, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::hs]);
if (strstr(source, " mainHS("))
{
compiled._numStages++;
vDefines[typeIndex] = "_HS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), &inc, _C(entryHS), "hs", flags, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::hs]);
}
vDefines[typeIndex] = "_DS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), _C(entryDS), "ds", 0, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::ds]);
if (strstr(source, " mainDS("))
{
compiled._numStages++;
vDefines[typeIndex] = "_DS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), &inc, _C(entryDS), "ds", flags, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::ds]);
}
vDefines[typeIndex] = "_GS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), _C(entryGS), "gs", 0, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::gs]);
if (strstr(source, " mainGS("))
{
compiled._numStages++;
vDefines[typeIndex] = "_GS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), &inc, _C(entryGS), "gs", flags, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::gs]);
}
vDefines[typeIndex] = "_FS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), _C(entryFS), "fs", 0, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::fs]);
if (strstr(source, " mainFS("))
{
compiled._numStages++;
vDefines[typeIndex] = "_FS";
if (!RendererVulkan::VerusCompile(source, vDefines.data(), &inc, _C(entryFS), "fs", flags, &pCode, &size, &pErrorMsgs))
CheckErrorMsgs(pErrorMsgs);
CreateShaderModule(pCode, size, compiled._shaderModules[+Stage::fs]);
}
_mapCompiled[entry] = compiled;

View File

@ -8,7 +8,8 @@ namespace verus
{
struct Compiled
{
VkShaderModule _shaderModules[+Stage::count] = { VK_NULL_HANDLE };
VkShaderModule _shaderModules[+Stage::count] = {};
int _numStages = 0;
};
VERUS_TYPEDEFS(Compiled);
typedef Map<String, Compiled> TMapCompiled;
@ -27,6 +28,7 @@ namespace verus
//
VkShaderModule GetVkShaderModule(CSZ branch, Stage stage) const { return _mapCompiled.at(branch)._shaderModules[+stage]; }
int GetNumStages(CSZ branch) const { return _mapCompiled.at(branch)._numStages; }
void OnError(CSZ s);
};

View File

@ -19,5 +19,9 @@ void TextureVulkan::Init(RcTextureDesc desc)
void TextureVulkan::Done()
{
VERUS_QREF_RENDERER_VULKAN;
VERUS_VULKAN_DESTROY(_imageView, vkDestroyImageView(pRendererVulkan->GetVkDevice(), _imageView, pRendererVulkan->GetAllocator()));
VERUS_DONE(TextureVulkan);
}

View File

@ -6,7 +6,8 @@ namespace verus
{
class TextureVulkan : public BaseTexture
{
VkImage _image = VK_NULL_HANDLE;
VkImage _image = VK_NULL_HANDLE;
VkImageView _imageView = VK_NULL_HANDLE;
public:
TextureVulkan();
@ -20,6 +21,7 @@ namespace verus
//
VkImage GetVkImage() const { return _image; }
VkImageView GetVkImageView() const { return _imageView; }
};
VERUS_TYPEDEFS(TextureVulkan);
}

View File

@ -93,6 +93,7 @@
<ClInclude Include="src\AI\Turret.h" />
<ClInclude Include="src\Anim\Anim.h" />
<ClInclude Include="src\Anim\Animation.h" />
<ClInclude Include="src\Anim\Damping.h" />
<ClInclude Include="src\Anim\Motion.h" />
<ClInclude Include="src\Anim\Skeleton.h" />
<ClInclude Include="src\App\App.h" />
@ -122,6 +123,7 @@
<ClInclude Include="src\D\Recoverable.h" />
<ClInclude Include="src\D\RuntimeError.h" />
<ClInclude Include="src\Game\BaseGame.h" />
<ClInclude Include="src\Game\Spirit.h" />
<ClInclude Include="src\Game\Game.h" />
<ClInclude Include="src\Game\State.h" />
<ClInclude Include="src\Game\StateMachine.h" />
@ -219,6 +221,7 @@
<ClCompile Include="src\CGI\RenderPass.cpp" />
<ClCompile Include="src\D\Log.cpp" />
<ClCompile Include="src\Game\BaseGame.cpp" />
<ClCompile Include="src\Game\Spirit.cpp" />
<ClCompile Include="src\Game\State.cpp" />
<ClCompile Include="src\Game\StateMachine.cpp" />
<ClCompile Include="src\Global\AllocatorAware.cpp" />

View File

@ -375,6 +375,12 @@
<ClInclude Include="src\CGI\Types.h">
<Filter>src\CGI</Filter>
</ClInclude>
<ClInclude Include="src\Anim\Damping.h">
<Filter>src\Anim</Filter>
</ClInclude>
<ClInclude Include="src\Game\Spirit.h">
<Filter>src\Game</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\CGI\BaseGeometry.cpp">
@ -584,5 +590,8 @@
<ClCompile Include="src\CGI\RenderPass.cpp">
<Filter>src\CGI</Filter>
</ClCompile>
<ClCompile Include="src\Game\Spirit.cpp">
<Filter>src\Game</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -1,5 +1,6 @@
#pragma once
#include "Damping.h"
#include "Motion.h"
#include "Skeleton.h"
#include "Animation.h"

96
Verus/src/Anim/Damping.h Normal file
View File

@ -0,0 +1,96 @@
#pragma once
namespace verus
{
namespace Anim
{
//! Change value smoothly across multiple frames.
template<typename T, bool angle = false>
class Damping
{
T _target = 0;
T _actual = 0;
float _speed = 1;
float _rate = 1;
public:
Damping() { _rate = log(10.f); }
Damping(const T& x) : _target(x), _actual(x) { _rate = log(10.f); }
Damping(const T& x, float speed) : _target(x), _actual(x), _speed(speed) { _rate = log(10.f); }
void operator=(const T& x) { _target = x; }
operator const T&() const { return _actual; }
const T& GetTarget() const { return _target; }
void SetActual(const T& x) { _actual = x; }
void SetSpeed(float s) { _speed = s; }
void ForceTarget() { _actual = _target; }
void ForceTarget(const T& x) { _actual = _target = x; }
void Update()
{
if (angle)
{
VERUS_RT_ASSERT(_target >= T(-VERUS_PI) && _target < T(VERUS_PI));
VERUS_RT_ASSERT(_actual >= T(-VERUS_PI) && _actual < T(VERUS_PI));
const T d = _target - _actual;
if (d > T(VERUS_PI))
_actual += VERUS_2PI;
else if (d < T(-VERUS_PI))
_actual -= VERUS_2PI;
}
if (0 == _speed)
{
_actual = _target;
}
else
{
VERUS_QREF_TIMER;
const float ratio = 1 / exp(_speed*dt*_rate);
_actual = Math::Lerp(_target, _actual, ratio);
if (angle)
_actual = Math::WrapAngle(_actual);
}
}
};
//! See Damping.
template<>
class Damping<Point3, false>
{
typedef Point3 T;
T _target = 0;
T _actual = 0;
float _speed = 1;
float _rate = 1;
public:
Damping() { _rate = log(10.f); }
Damping(const T& x) : _target(x), _actual(x) { _rate = log(10.f); }
Damping(const T& x, float speed) : _target(x), _actual(x), _speed(speed) { _rate = log(10.f); }
void operator=(const T& x) { _target = x; }
operator const T&() const { return _actual; }
const T& GetTarget() const { return _target; }
void SetActual(const T& x) { _actual = x; }
void SetSpeed(float s) { _speed = s; }
void ForceTarget() { _actual = _target; }
void ForceTarget(const T& x) { _actual = _target = x; }
void Update()
{
if (0 == _speed)
{
_actual = _target;
}
else
{
VERUS_QREF_TIMER;
const float ratio = 1 / exp(_speed*dt*_rate);
_actual = VMath::lerp(ratio, _target, _actual);
}
}
};
}
}

View File

@ -753,13 +753,13 @@ void Skeleton::BakeMotion(RMotion motion, int frame, bool kinect)
Quat q(mat.getUpper3x3());
Vector3 pos = mat.getTranslation();
if (glm::epsilonEqual<float>(q.getX(), 0, 1e-4f)) q.setX(0);
if (glm::epsilonEqual<float>(q.getY(), 0, 1e-4f)) q.setY(0);
if (glm::epsilonEqual<float>(q.getZ(), 0, 1e-4f)) q.setZ(0);
if (glm::epsilonEqual<float>(q.getW(), 1, 1e-4f)) q.setW(1);
if (glm::epsilonEqual<float>(pos.getX(), 0, 1e-4f)) pos.setX(0);
if (glm::epsilonEqual<float>(pos.getY(), 0, 1e-4f)) pos.setY(0);
if (glm::epsilonEqual<float>(pos.getZ(), 0, 1e-4f)) pos.setZ(0);
if (glm::epsilonEqual<float>(q.getX(), 0, VERUS_FLOAT_THRESHOLD)) q.setX(0);
if (glm::epsilonEqual<float>(q.getY(), 0, VERUS_FLOAT_THRESHOLD)) q.setY(0);
if (glm::epsilonEqual<float>(q.getZ(), 0, VERUS_FLOAT_THRESHOLD)) q.setZ(0);
if (glm::epsilonEqual<float>(q.getW(), 1, VERUS_FLOAT_THRESHOLD)) q.setW(1);
if (glm::epsilonEqual<float>(pos.getX(), 0, VERUS_FLOAT_THRESHOLD)) pos.setX(0);
if (glm::epsilonEqual<float>(pos.getY(), 0, VERUS_FLOAT_THRESHOLD)) pos.setY(0);
if (glm::epsilonEqual<float>(pos.getZ(), 0, VERUS_FLOAT_THRESHOLD)) pos.setZ(0);
if (!Math::IsNaN(q.getX()) &&
!Math::IsNaN(q.getY()) &&

View File

@ -2,3 +2,23 @@
using namespace verus;
using namespace verus::CGI;
// CommandBufferPtr:
void CommandBufferPtr::Init()
{
VERUS_QREF_RENDERER;
VERUS_RT_ASSERT(!_p);
_p = renderer->InsertCommandBuffer();
_p->Init();
}
void CommandBufferPwn::Done()
{
if (_p)
{
VERUS_QREF_RENDERER;
renderer->DeleteCommandBuffer(_p);
_p = nullptr;
}
}

View File

@ -17,22 +17,43 @@ namespace verus
virtual void Begin() = 0;
virtual void End() = 0;
virtual void BeginRenderPass() = 0;
virtual void BeginRenderPass(int renderPassID, int framebufferID, std::initializer_list<Vector4> ilClearValues, PcVector4 pRenderArea = nullptr) = 0;
virtual void EndRenderPass() = 0;
virtual void BindVertexBuffers() = 0;
virtual void BindIndexBuffer() = 0;
virtual void BindVertexBuffers(GeometryPtr geo) = 0;
virtual void BindIndexBuffer(GeometryPtr geo) = 0;
virtual void SetScissor() = 0;
virtual void SetViewport() = 0;
virtual void SetScissor(std::initializer_list<Vector4> il) = 0;
virtual void SetViewport(std::initializer_list<Vector4> il, float minDepth = 0, float maxDepth = 1) = 0;
virtual void BindPipeline() = 0;
virtual void BindPipeline(PipelinePtr pipe) = 0;
virtual void PushConstant(PipelinePtr pipe, int offset, int size, const void* p) = 0;
virtual void PipelineBarrier(TexturePtr tex, ImageLayout oldLayout, ImageLayout newLayout) = 0;
virtual void Clear(ClearFlags clearFlags) = 0;
virtual void Draw() = 0;
virtual void DrawIndexed() = 0;
virtual void Draw(int vertexCount, int instanceCount, int firstVertex = 0, int firstInstance = 0) = 0;
virtual void DrawIndexed(int indexCount, int instanceCount, int firstIndex = 0, int vertexOffset = 0, int firstInstance = 0) = 0;
};
VERUS_TYPEDEFS(BaseCommandBuffer);
class CommandBufferPtr : public Ptr<BaseCommandBuffer>
{
public:
void Init();
};
VERUS_TYPEDEFS(CommandBufferPtr);
class CommandBufferPwn : public CommandBufferPtr
{
public:
~CommandBufferPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(CommandBufferPwn);
template<int NUM>
class CommandBufferPwns : public Pwns<CommandBufferPwn, NUM>
{
};
}
}

View File

@ -2,3 +2,54 @@
using namespace verus;
using namespace verus::CGI;
int BaseGeometry::GetNumInputElementDesc(PcInputElementDesc p)
{
int i = 0;
while (p[i]._offset >= 0)
i++;
return i;
}
int BaseGeometry::GetNumBindings(PcInputElementDesc p)
{
int num = 0;
int i = 0;
while (p[i]._offset >= 0)
{
bool found = false;
int j = 0;
while (j < i)
{
if (p[j]._binding == p[i]._binding)
{
found = true;
break;
}
}
if (!found)
num++;
i++;
}
return num;
}
// GeometryPtr:
void GeometryPtr::Init(RcGeometryDesc desc)
{
VERUS_QREF_RENDERER;
VERUS_RT_ASSERT(!_p);
_p = renderer->InsertGeometry();
_p->Init(desc);
}
void GeometryPwn::Done()
{
if (_p)
{
VERUS_QREF_RENDERER;
renderer->DeleteGeometry(_p);
_p = nullptr;
}
}

View File

@ -6,20 +6,53 @@ namespace verus
{
struct GeometryDesc
{
bool _dwordIndices = false;
PcInputElementDesc _pInputElementDesc;
const int* _pStrides = nullptr;
bool _32bitIndices = false;
};
VERUS_TYPEDEFS(GeometryDesc);
class BaseGeometry : public Object
{
protected:
int _bindingInstMask = 0;
bool _32bitIndices = false;
BaseGeometry() = default;
virtual ~BaseGeometry() = default;
public:
virtual void Init(RcGeometryDesc desc) = 0;
virtual void Done() = 0;
virtual void BufferDataVB(const void* p, int num, int binding) = 0;
virtual void BufferDataIB(const void* p, int num) = 0;
static int GetNumInputElementDesc(PcInputElementDesc p);
static int GetNumBindings(PcInputElementDesc p);
bool Has32bitIndices() const { return _32bitIndices; }
};
VERUS_TYPEDEFS(BaseGeometry);
class GeometryPtr : public Ptr<BaseGeometry>
{
public:
void Init(RcGeometryDesc desc);
};
VERUS_TYPEDEFS(GeometryPtr);
class GeometryPwn : public GeometryPtr
{
public:
~GeometryPwn() { Done(); }
void Done();
};
VERUS_TYPEDEFS(GeometryPwn);
template<int NUM>
class GeometryPwns : public Pwns<GeometryPwn, NUM>
{
};
}
}

View File

@ -2,3 +2,23 @@
using namespace verus;
using namespace verus::CGI;
// PipelinePtr:
void PipelinePtr::Init(RcPipelineDesc desc)
{
VERUS_QREF_RENDERER;
VERUS_RT_ASSERT(!_p);
_p = renderer->InsertPipeline();
_p->Init(desc);
}
void PipelinePwn::Done()
{
if (_p)
{
VERUS_QREF_RENDERER;
renderer->DeletePipeline(_p);
_p = nullptr;
}
}

View File

@ -6,14 +6,17 @@ namespace verus
{
struct PipelineDesc
{
Vector4 _viewport;
Vector4 _scissor;
RcBaseShader _shader;
GeometryPtr _geometry;
ShaderPtr _shader;
CSZ _shaderBranch = nullptr;
PipelineRasterizationState _rasterizationState;
PrimitiveTopology _topology = PrimitiveTopology::triangleList;
int _sampleCount = 1;
bool _primitiveRestartEnable = false;
int _renderPassID = -1;
PipelineDesc(GeometryPtr geo, ShaderPtr shader, CSZ branch, int renderPassID) :
_geometry(geo), _shader(shader), _shaderBranch(branch), _renderPassID(renderPassID) {}
};
VERUS_TYPEDEFS(PipelineDesc);

View File

@ -25,10 +25,10 @@ namespace verus
class BaseRenderer : public Object
{
protected:
BaseRendererDesc _desc;
UINT32 _numSwapChainBuffers = 0;
UINT32 _swapChainBufferIndex = 0;
UINT32 _ringBufferIndex = 0;
BaseRendererDesc _desc;
UINT32 _numSwapChainBuffers = 0;
UINT32 _swapChainBufferIndex = 0;
UINT32 _ringBufferIndex = 0;
BaseRenderer();
virtual ~BaseRenderer();
@ -50,23 +50,30 @@ namespace verus
virtual Gapi GetGapi() = 0;
// Frame cycle:
virtual void BeginFrame() = 0;
virtual void EndFrame() = 0;
virtual void BeginFrame(bool present = true) = 0;
virtual void EndFrame(bool present = true) = 0;
virtual void Present() = 0;
virtual void Clear(UINT32 flags) = 0;
// Resources:
virtual PBaseCommandBuffer InsertCommandBuffer() { return nullptr; }
virtual PBaseGeometry InsertGeometry() { return nullptr; }
virtual PBasePipeline InsertPipeline() { return nullptr; }
virtual PBaseShader InsertShader() { return nullptr; }
virtual PBaseTexture InsertTexture() { return nullptr; }
virtual void WaitIdle() = 0;
virtual void DeleteCommandBuffer(PBaseCommandBuffer p) {}
virtual void DeleteGeometry(PBaseGeometry p) {}
virtual void DeletePipeline(PBasePipeline p) {}
virtual void DeleteShader(PBaseShader p) {}
virtual void DeleteTexture(PBaseTexture p) {}
// Resources:
virtual PBaseCommandBuffer InsertCommandBuffer() = 0;
virtual PBaseGeometry InsertGeometry() = 0;
virtual PBasePipeline InsertPipeline() = 0;
virtual PBaseShader InsertShader() = 0;
virtual PBaseTexture InsertTexture() = 0;
virtual void DeleteCommandBuffer(PBaseCommandBuffer p) = 0;
virtual void DeleteGeometry(PBaseGeometry p) = 0;
virtual void DeletePipeline(PBasePipeline p) = 0;
virtual void DeleteShader(PBaseShader p) = 0;
virtual void DeleteTexture(PBaseTexture p) = 0;
virtual int CreateRenderPass(std::initializer_list<RP::Attachment> ilA, std::initializer_list<RP::Subpass> ilS, std::initializer_list<RP::Dependency> ilD) { return 0; }
virtual int CreateFramebuffer(int renderPassID, std::initializer_list<TexturePtr> il, int w, int h, int swapChainBufferIndex = -1) { return 0; }
virtual void DeleteRenderPass(int id) {}
virtual void DeleteFramebuffer(int id) {}
};
VERUS_TYPEDEFS(BaseRenderer);
}

View File

@ -3,6 +3,8 @@
using namespace verus;
using namespace verus::CGI;
CSZ BaseShader::s_branchCommentMarker = "//@";
void BaseShader::Load(CSZ url)
{
Vector<BYTE> vData;
@ -10,13 +12,14 @@ void BaseShader::Load(CSZ url)
Vector<String> vBranches;
CSZ pSource = reinterpret_cast<CSZ>(vData.data());
CSZ p = strstr(pSource, "//@");
CSZ p = strstr(pSource, s_branchCommentMarker);
const size_t branchCommentMarkerLen = strlen(s_branchCommentMarker);
while (p)
{
const size_t span = strcspn(p, VERUS_CRNL);
const String value(p + 3, span - 3);
const String value(p + branchCommentMarkerLen, span - branchCommentMarkerLen);
vBranches.push_back(value);
p = strstr(p + span, "//@");
p = strstr(p + span, s_branchCommentMarker);
}
Vector<CSZ> vBranchPtrs;
@ -145,7 +148,7 @@ void ShaderPtr::Init(RcShaderDesc desc)
{
VERUS_QREF_RENDERER;
VERUS_RT_ASSERT(!_p);
//_p = render->InsertShader();
_p = renderer->InsertShader();
_p->SetIgnoreList(desc._ignoreList);
_p->SetSaveCompiled(desc._saveCompiled);
if (desc._url)
@ -159,7 +162,7 @@ void ShaderPwn::Done()
if (_p)
{
VERUS_QREF_RENDERER;
//render->DeleteShader(_p);
renderer->DeleteShader(_p);
_p = nullptr;
}
}

View File

@ -16,6 +16,8 @@ namespace verus
class BaseShader : public Object
{
static CSZ s_branchCommentMarker;
public:
enum class Stage : int
{

View File

@ -1,8 +1,11 @@
#pragma once
#define VERUS_CGI_MAX_RT 8
#include "Types.h"
#include "Formats.h"
#include "RenderPass.h"
#include "BaseGeometry.h"
#include "BaseShader.h"
#include "BasePipeline.h"

View File

@ -27,6 +27,8 @@ namespace verus
int _sampleCount = 1;
LoadOp _loadOp = LoadOp::load;
StoreOp _storeOp = StoreOp::store;
LoadOp _stencilLoadOp = LoadOp::dontCare;
StoreOp _stencilStoreOp = StoreOp::dontCare;
ImageLayout _initialLayout = ImageLayout::undefined;
ImageLayout _finalLayout = ImageLayout::undefined;
@ -40,17 +42,20 @@ namespace verus
};
VERUS_TYPEDEFS(Attachment);
class Ref
{
public:
CSZ _name = nullptr;
ImageLayout _layout = ImageLayout::undefined;
Ref() = default;
Ref(CSZ name, ImageLayout layout) : _name(name), _layout(layout) {}
};
VERUS_TYPEDEFS(Ref);
class Subpass
{
public:
struct Ref
{
CSZ _name = nullptr;
ImageLayout _layout = ImageLayout::undefined;
Ref() {}
};
CSZ _name = nullptr;
std::initializer_list<Ref> _ilInput;
std::initializer_list<Ref> _ilColor;

View File

@ -46,12 +46,44 @@ void Renderer::Init(PRendererDelegate pDelegate)
_pBaseRenderer = BaseRenderer::Load(dll, desc);
_gapi = _pBaseRenderer->GetGapi();
_commandBuffer.Init();
_rpSwapChain = _pBaseRenderer->CreateRenderPass(
{ RP::Attachment("Color", Format::unormB8G8R8A8).LoadOpClear().FinalLayout(ImageLayout::presentSrc) },
{ RP::Subpass("Sp0").Color({RP::Ref("Color", ImageLayout::colorAttachmentOptimal)}) },
{});
_rpDS = _pBaseRenderer->CreateRenderPass(
{
RP::Attachment("GBuffer0", Format::unormR8G8B8A8).LoadOpClear().FinalLayout(ImageLayout::presentSrc),
RP::Attachment("GBuffer1", Format::unormR8G8B8A8).LoadOpClear().FinalLayout(ImageLayout::presentSrc),
RP::Attachment("GBuffer2", Format::unormR8G8B8A8).LoadOpClear().FinalLayout(ImageLayout::presentSrc),
RP::Attachment("GBuffer3", Format::unormR8G8B8A8).LoadOpClear().FinalLayout(ImageLayout::presentSrc),
RP::Attachment("Depth", Format::unormD24uintS8).LoadOpClear().FinalLayout(ImageLayout::presentSrc),
},
{
RP::Subpass("Sp0").Color(
{
RP::Ref("GBuffer0", ImageLayout::colorAttachmentOptimal),
RP::Ref("GBuffer1", ImageLayout::colorAttachmentOptimal),
RP::Ref("GBuffer2", ImageLayout::colorAttachmentOptimal),
RP::Ref("GBuffer3", ImageLayout::colorAttachmentOptimal)
}).DepthStencil(RP::Ref("Depth", ImageLayout::depthStencilAttachmentOptimal))
},
{
});
_fbSwapChain.resize(_pBaseRenderer->GetNumSwapChainBuffers());
VERUS_FOR(i, _fbSwapChain.size())
_fbSwapChain[i] = _pBaseRenderer->CreateFramebuffer(_rpSwapChain, {}, settings._screenSizeWidth, settings._screenSizeHeight, i);
}
void Renderer::Done()
{
if (_pBaseRenderer)
{
_pBaseRenderer->WaitIdle();
_commandBuffer.Done();
_pBaseRenderer->ReleaseMe();
_pBaseRenderer = nullptr;
}
@ -86,3 +118,9 @@ void Renderer::OnShaderWarning(CSZ s)
{
VERUS_LOG_WARN("Shader Warning:\n" << s);
}
float Renderer::GetWindowAspectRatio() const
{
VERUS_QREF_SETTINGS;
return static_cast<float>(settings._screenSizeWidth) / static_cast<float>(settings._screenSizeHeight);
}

View File

@ -19,11 +19,13 @@ namespace verus
App::PWindow _pMainWindow = nullptr;
PBaseRenderer _pBaseRenderer = nullptr;
PRendererDelegate _pRendererDelegate = nullptr;
CommandBufferPwn _commandBuffer;
UINT64 _numFrames = 0;
Gapi _gapi = Gapi::unknown;
float _fps = 30;
ShaderPwn _sTest;
int _rpSwapChain = 0;
int _rpDS = 0;
Vector<int> _fbSwapChain;
public:
Renderer();
@ -40,11 +42,14 @@ namespace verus
void Draw();
void Present();
CommandBufferPtr GetCommandBuffer() const { return _commandBuffer; }
void OnShaderError(CSZ s);
void OnShaderWarning(CSZ s);
App::PWindow GetMainWindow() const { return _pMainWindow; }
App::PWindow SetMainWindow(App::PWindow p) { return Utils::Swap(_pMainWindow, p); }
float GetWindowAspectRatio() const;
RcVector4 GetClearColor() const { return _clearColor; }
void SetClearColor(RcVector4 color) { _clearColor = color; }
@ -52,6 +57,11 @@ namespace verus
// Frame rate:
float GetFps() const { return _fps; }
UINT64 GetNumFrames() const { return _numFrames; }
int GetRenderPassSwapChain() const { return _rpSwapChain; }
int GetRenderPassDS() const { return _rpDS; }
int GetFramebufferSwapChain(int index) const { return _fbSwapChain[index]; }
};
VERUS_TYPEDEFS(Renderer);
}

View File

@ -46,12 +46,6 @@ namespace verus
triangleStrip
};
struct PipelineInputAssemblyState
{
PrimitiveTopology _topology = PrimitiveTopology::triangleList;
bool _primitiveRestartEnable = false;
};
struct PipelineRasterizationState
{
PolygonMode _polygonMode = PolygonMode::fill;
@ -60,9 +54,44 @@ namespace verus
float _depthBiasClamp = 0;
float _depthBiasSlopeFactor = 0;
float _lineWidth = 1;
bool _depthClampEnable = true;
bool _depthClampEnable = false;
bool _depthBiasEnable = false;
bool _rasterizerDiscardEnable = false;
};
enum class IeType : int
{
_float,
_ubyte,
_short
};
// See: https://docs.microsoft.com/en-us/windows/desktop/direct3d9/d3ddeclusage
enum class IeUsage : int
{
position,
blendWeight,
blendIndices,
normal,
psize,
texCoord,
tangent,
binormal,
color
};
// See: https://docs.microsoft.com/en-us/windows/desktop/direct3d9/d3dvertexelement9
struct InputElementDesc
{
int _binding;
int _offset;
IeType _type;
int _components;
IeUsage _usage;
int _usageIndex;
static constexpr InputElementDesc End() { return { -1, -1, IeType::_float, 0, IeUsage::position, 0 }; }
};
VERUS_TYPEDEFS(InputElementDesc);
}
}

View File

@ -16,7 +16,6 @@ struct MyRendererDelegate : CGI::RendererDelegate
VERUS_QREF_TIMER;
const float x = fmod(timer.GetTime(), 1.f);
renderer.SetClearColor(Vector4(x, 0.5f, 0.25f, 1.f));
renderer->BeginFrame();
renderer->Clear(0);
_p->BaseGame_Draw();
}
@ -29,7 +28,6 @@ struct MyRendererDelegate : CGI::RendererDelegate
virtual void Renderer_OnPresent() override
{
VERUS_QREF_RENDERER;
renderer->EndFrame();
renderer->Present();
}
@ -43,7 +41,7 @@ struct BaseGame::Pimpl : AllocatorAware
{
PBaseGame _p = nullptr;
Scene::MainCamera _camera;
//CCharacter _cameraCharacter;
Spirit _cameraSpirit;
bool _defaultCameraMovement = true;
bool _showFPS = true;
bool _debugBullet = false;
@ -109,12 +107,14 @@ void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS)
_engineInit.Init(this, new MyRendererDelegate(this));
// Configure:
//VERUS_QREF_RENDER;
VERUS_QREF_RENDERER;
//VERUS_QREF_SM;
//_p->_camera.SetAspectRatio(render.GetWindowAspectRatio());
_p->_camera.SetAspectRatio(renderer.GetWindowAspectRatio());
//sm.SetCamera(&_p->_camera);
renderer->BeginFrame(false); // Begin recording a command buffer.
BaseGame_LoadContent();
renderer->EndFrame(false); // End recording a command buffer.
}
void BaseGame::Run()
@ -180,36 +180,36 @@ void BaseGame::Run()
//
// UPDATE
// At this point the user sees a frame drawn some time ago.
//
renderer->BeginFrame();
async.Update();
timer.Update(); // Now we know how much time has passed. Maybe 1 hour!
timer.Update();
// Process input for simulation:
if (_p->_defaultCameraMovement)
{
const float speed = km.IsKeyPressed(SDL_SCANCODE_SPACE) ? 20.f : 2.f;
//if (km.IsKeyPressed(SDL_SCANCODE_W))
// _p->_cameraCharacter.MoveFront(speed);
//if (km.IsKeyPressed(SDL_SCANCODE_S))
// _p->_cameraCharacter.MoveFront(-speed);
//if (km.IsKeyPressed(SDL_SCANCODE_A))
// _p->_cameraCharacter.MoveSide(-speed);
//if (km.IsKeyPressed(SDL_SCANCODE_D))
// _p->_cameraCharacter.MoveSide(speed);
if (km.IsKeyPressed(SDL_SCANCODE_W))
_p->_cameraSpirit.MoveFront(speed);
if (km.IsKeyPressed(SDL_SCANCODE_S))
_p->_cameraSpirit.MoveFront(-speed);
if (km.IsKeyPressed(SDL_SCANCODE_A))
_p->_cameraSpirit.MoveSide(-speed);
if (km.IsKeyPressed(SDL_SCANCODE_D))
_p->_cameraSpirit.MoveSide(speed);
}
BaseGame_HandleInput();
//bullet.Simulate(); // x += v*dt.
//bullet.Simulate();
// Update game state after simulation:
if (_p->_defaultCameraMovement)
{
//_p->_cameraCharacter.Update(); // Get position from Bullet.
//_p->_camera.MoveEyeTo(_p->_cameraCharacter.GetPosition());
//_p->_camera.MoveAtTo(_p->_cameraCharacter.GetPosition() + _p->_cameraCharacter.GetDirectionFront());
_p->_cameraSpirit.HandleInput();
_p->_cameraSpirit.Update();
_p->_camera.MoveEyeTo(_p->_cameraSpirit.GetPosition());
_p->_camera.MoveAtTo(_p->_cameraSpirit.GetPosition() + _p->_cameraSpirit.GetDirectionFront());
//if (Scene::CWater::IsValidSingleton())
{
// VERUS_QREF_WATER;
@ -218,6 +218,7 @@ void BaseGame::Run()
}
_p->_camera.Update();
}
BaseGame_Update();
asys.Update();
@ -225,7 +226,8 @@ void BaseGame::Run()
// Draw current frame:
renderer.Draw();
km.ResetClickState();
renderer.Present(); // This can take a while.
renderer->EndFrame();
renderer.Present();
// Show FPS:
if (_p->_showFPS && timer.IsEventEvery(500))
@ -256,13 +258,15 @@ void BaseGame::KeyMapper_OnMouseMove(int x, int y)
{
VERUS_QREF_CONST_SETTINGS;
const float fx = x * 0.006f*settings._inputMouseSensitivity;
const float fy = y * 0.006f*settings._inputMouseSensitivity;
const float rad = (VERUS_2PI / 360.f) / 3.f; // 3 pixels = 1 degree.
const float scale = rad * settings._inputMouseSensitivity;
const float fx = x * scale;
const float fy = y * scale;
if (_p->_defaultCameraMovement)
{
//_p->_cameraCharacter.TurnPitch(fy);
//_p->_cameraCharacter.TurnYaw(fx);
_p->_cameraSpirit.TurnPitch(fy);
_p->_cameraSpirit.TurnYaw(fx);
}
BaseGame_OnMouseMove(fx, fy);
@ -284,9 +288,9 @@ Scene::RCamera BaseGame::GetCamera()
}
#if 0
RCharacter BaseGame::GetCameraCharacter()
RSpirit BaseGame::GetCameraSpirit()
{
return _p->_cameraCharacter;
return _p->_cameraSpirit;
}
#endif

View File

@ -38,7 +38,7 @@ namespace verus
// Internal objects:
Scene::RCamera GetCamera();
//RCharacter GetCameraCharacter();
RSpirit GetCameraSpirit();
// Configurations:
void ActivateDefaultCameraMovement(bool b);

View File

@ -2,4 +2,5 @@
#include "State.h"
#include "StateMachine.h"
#include "Spirit.h"
#include "BaseGame.h"

223
Verus/src/Game/Spirit.cpp Normal file
View File

@ -0,0 +1,223 @@
#include "verus.h"
using namespace verus;
using namespace verus::Game;
const float Spirit::s_defaultMaxPitch = VERUS_PI * (44.5f / 90.f);
Spirit::Spirit() :
_smoothPosition(Point3(0), 10),
_pitch(0, 10),
_yaw(0, 10)
{
ComputeDerivedVars();
}
Spirit::~Spirit()
{
}
void Spirit::ComputeDerivedVars()
{
_dv._matPitch = Matrix3::rotationX(_pitch);
_dv._matYaw = Matrix3::rotationY(_yaw);
_dv._matRot = _dv._matYaw*_dv._matPitch;
_dv._dirFront = _dv._matRot*Vector3(0, 0, 1);
_dv._dirFront2D = _dv._matYaw*Vector3(0, 0, 1);
_dv._dirSide = VMath::normalizeApprox(VMath::cross(_dv._dirFront, Vector3(0, 1, 0)));
_dv._dirSide2D = VMath::normalizeApprox(VMath::cross(_dv._dirFront2D, Vector3(0, 1, 0)));
}
void Spirit::MoveFront(float x)
{
_move += _dv._dirFront*x;
}
void Spirit::MoveSide(float x)
{
_move += _dv._dirSide*x;
}
void Spirit::MoveFront2D(float x)
{
_move += _dv._dirFront2D*x;
}
void Spirit::MoveSide2D(float x)
{
_move += _dv._dirSide2D*x;
}
void Spirit::TurnPitch(float rad)
{
_pitch = _pitch.GetTarget() + rad;
_pitch = Math::Clamp<float>(_pitch.GetTarget(), -_maxPitch, _maxPitch);
}
void Spirit::TurnYaw(float rad)
{
_yaw = Math::WrapAngle(_yaw.GetTarget() - rad);
}
void Spirit::SetPitch(float rad)
{
_pitch = rad;
}
void Spirit::SetYaw(float rad)
{
_yaw = Math::WrapAngle(rad);
}
void Spirit::HandleInput()
{
VERUS_QREF_TIMER;
// Update velocity:
if (_accel)
{
}
else // No accel:
{
_velocity = _move;
}
// At this point _move == _velocity.
}
void Spirit::Update()
{
VERUS_QREF_TIMER;
_pitch.Update();
_yaw.Update();
ComputeDerivedVars();
// Update position:
_positionPrev = _position;
_smoothPositionPrev = _smoothPosition;
{
_position += _velocity * dt;
}
_smoothPosition = _position;
_smoothPosition.Update();
_speed = VMath::dist(_smoothPosition, _smoothPositionPrev)*timer.GetDeltaTimeInv();
// Friction:
if (_decel && _moveLen < VERUS_FLOAT_THRESHOLD)
{
{
float speed = VMath::length(_velocity);
if (speed >= VERUS_FLOAT_THRESHOLD)
{
const Vector3 dir = _velocity / speed;
//speed = Math::Reduce(speed, _decel*dt);
_velocity = dir * speed;
}
}
}
_move = Vector3(0);
}
void Spirit::SetAcceleration(float accel, float decel)
{
_accel = accel;
_decel = decel;
}
Point3 Spirit::GetPosition(bool smooth)
{
return smooth ? static_cast<Point3>(_smoothPosition) : _position;
}
void Spirit::MoveTo(RcPoint3 pos, float onTerrain)
{
_position = pos;
_positionPrev = _position;
_smoothPosition.ForceTarget(_position);
_smoothPositionPrev = _position;
}
void Spirit::SetRemotePosition(RcPoint3 pos)
{
_positionRemote = pos;
}
bool Spirit::FitRemotePosition()
{
VERUS_QREF_TIMER;
const Point3 pos = _position;
const float d = Math::Max(9.f, VMath::distSqr(_positionRemote, pos) * 4);
const float ratio = 1 / exp(dt*d);
const bool warp = d >= 4 * 4;
_position = warp ? _positionRemote : VMath::lerp(ratio, _positionRemote, pos);
if (warp)
{
_positionPrev = _position;
_smoothPosition.ForceTarget(_position);
_smoothPositionPrev = _position;
}
_positionRemote += _velocity * dt; // Predict.
return warp;
}
void Spirit::Rotate(RcVector3 front, float speed)
{
VERUS_QREF_TIMER;
const Vector3 dir = front;
const float yaw = Math::WrapAngle(atan2(
static_cast<float>(dir.getX()),
static_cast<float>(dir.getZ())));
Vector3 dir2D = dir;
dir2D.setY(0);
const float pitch = -atan(dir.getY() / VMath::length(dir2D));
float dPitch = pitch - _pitch;
float dYaw = yaw - _yaw;
if (dYaw >= VERUS_PI)
dYaw -= VERUS_2PI;
if (dYaw <= -VERUS_PI)
dYaw += VERUS_2PI;
_pitch = _pitch + Math::Min(speed*dt, abs(dPitch))*glm::sign(dPitch);
_yaw = Math::WrapAngle(_yaw + Math::Min(speed*dt, abs(dYaw))*glm::sign(dYaw));
}
void Spirit::LookAt(RcPoint3 point)
{
const Vector3 dir = point - GetPosition();
_yaw = Math::WrapAngle(atan2(
static_cast<float>(dir.getX()),
static_cast<float>(dir.getZ())));
Vector3 dir2D = dir;
dir2D.setY(0);
_pitch = -atan(dir.getY() / VMath::length(dir2D));
}
RcMatrix3 Spirit::GetPitchMatrix() const
{
return _dv._matPitch;
}
RcMatrix3 Spirit::GetYawMatrix() const
{
return _dv._matYaw;
}
RcMatrix3 Spirit::GetRotationMatrix() const
{
return _dv._matRot;
}
Transform3 Spirit::GetMatrix() const
{
return Transform3(_dv._matRot, Vector3(_smoothPosition));
}
Transform3 Spirit::GetUprightMatrix() const
{
return Transform3(_dv._matYaw, Vector3(_smoothPosition));
}

90
Verus/src/Game/Spirit.h Normal file
View File

@ -0,0 +1,90 @@
#pragma once
namespace verus
{
namespace Game
{
class Spirit : public AllocatorAware
{
static const float s_defaultMaxPitch;
struct DerivedVars
{
Matrix3 _matPitch;
Matrix3 _matYaw;
Matrix3 _matRot;
Vector3 _dirFront = Vector3(0);
Vector3 _dirFront2D = Vector3(0);
Vector3 _dirSide = Vector3(0);
Vector3 _dirSide2D = Vector3(0);
};
DerivedVars _dv;
Point3 _position = Point3(0);
Point3 _positionPrev = Point3(0);
Point3 _positionRemote = Point3(0);
Vector3 _velocity = Vector3(0);
Vector3 _move = Vector3(0);
Point3 _smoothPositionPrev = Point3(0);
Anim::Damping<Point3> _smoothPosition;
Anim::Damping<float, true> _pitch;
Anim::Damping<float, true> _yaw;
float _moveLen = 0;
float _maxPitch = s_defaultMaxPitch;
float _accel = 0;
float _decel = 0;
float _speed = 0;
float _maxSpeed = 10;
public:
Spirit();
virtual ~Spirit();
VERUS_P(void ComputeDerivedVars());
// Move:
void MoveFront(float x);
void MoveSide(float x);
void MoveFront2D(float x);
void MoveSide2D(float x);
void TurnPitch(float rad);
void TurnYaw(float rad);
void SetPitch(float rad);
void SetYaw(float rad);
void SetMaxPitch(float value = s_defaultMaxPitch) { _maxPitch = value; }
float GetPitch() const { return _pitch; }
float GetYaw() const { return _yaw; }
virtual void HandleInput();
virtual void Update();
void SetAcceleration(float accel = 5, float decel = 5);
float GetMaxSpeed() const { return _maxSpeed; }
void SetMaxSpeed(float v = 10) { _maxSpeed = v; }
Point3 GetPosition(bool smooth = true);
void MoveTo(RcPoint3 pos, float onTerrain = -1);
void SetRemotePosition(RcPoint3 pos);
bool FitRemotePosition();
RcVector3 GetVelocity() const { return _velocity; }
void SetVelocity(RcVector3 v) { _velocity = v; }
RcVector3 GetDirectionFront() const { return _dv._dirFront; }
RcVector3 GetDirectionSide() const { return _dv._dirSide; }
//! Rotates smoothly across multiple frames.
void Rotate(RcVector3 front, float speed);
void LookAt(RcPoint3 point);
// Matrices:
RcMatrix3 GetPitchMatrix() const;
RcMatrix3 GetYawMatrix() const;
RcMatrix3 GetRotationMatrix() const;
Transform3 GetMatrix() const;
Transform3 GetUprightMatrix() const;
};
VERUS_TYPEDEFS(Spirit);
}
}

View File

@ -20,6 +20,10 @@ void State::Update()
{
}
void State::Draw()
{
}
void State::OnExit(PState pNext)
{
}

View File

@ -14,6 +14,7 @@ namespace verus
virtual void OnEnter(State* pPrev);
virtual void HandleInput();
virtual void Update();
virtual void Draw();
virtual void OnExit(State* pNext);
};
VERUS_TYPEDEFS(State);

View File

@ -21,6 +21,14 @@ void StateMachine::Update()
_changed = (_pCurrentState != pCheck);
}
void StateMachine::Draw()
{
PcState pCheck = _pCurrentState;
_pCurrentState->_pStateMachine = this;
_pCurrentState->Draw();
_changed = (_pCurrentState != pCheck);
}
PState StateMachine::GetCurrentState() const
{
return _pCurrentState;
@ -45,7 +53,7 @@ bool StateMachine::EnterState(RState state, bool allowSameState)
if (!CanEnterState(state, allowSameState))
return false;
const UINT32 frame = /*CGL::CRender::I().GetNumFrames();*/ 0;
const UINT64 frame = CGI::Renderer::I().GetNumFrames();
VERUS_RT_ASSERT(frame != _prevFrame); // Don't change state multiple times per frame!
_prevFrame = frame;

View File

@ -8,14 +8,17 @@ namespace verus
{
PState _pCurrentState = nullptr;
PState _pRequestedState = nullptr;
UINT32 _prevFrame = -1;
UINT64 _prevFrame = UINT64_MAX;
bool _changed = false;
public:
void HandleInput();
void Update();
void Draw();
PState GetCurrentState() const;
PState GetRequestedState() const;
bool CanEnterState(RState state, bool allowSameState = false);
bool EnterState(RState state, bool allowSameState = false);
bool EnterRequestedState();

View File

@ -8,13 +8,13 @@
#include "Store.h"
#include "Blob.h"
#include "Random.h"
#include "Str.h"
#include "Utils.h"
#include "Parallel.h"
#include "Range.h"
#include "Object.h"
#include "Lockable.h"
#include "Linear.h"
#include "Str.h"
#include "Convert.h"
#include "Timer.h"
#include "EngineInit.h"

View File

@ -20,6 +20,8 @@ void Utils::MakeEx(PBaseAllocator pAlloc)
Utils* p = static_cast<Utils*>(pAlloc->malloc(sizeof(Utils)));
p = new(p)Utils(pAlloc);
p->InitPaths();
}
void Utils::FreeEx(PBaseAllocator pAlloc)
@ -34,6 +36,23 @@ void Utils::FreeEx(PBaseAllocator pAlloc)
TestAllocCount();
}
void Utils::InitPaths()
{
wchar_t pathName[MAX_PATH] = {};
GetModuleFileName(nullptr, pathName, MAX_PATH);
PathRemoveFileSpec(pathName);
_modulePath = Str::WideToUtf8(pathName);
_shaderPath = _modulePath + "/Data/Shaders";
SHGetSpecialFolderPath(0, pathName, CSIDL_LOCAL_APPDATA, TRUE);
_writablePath = Str::WideToUtf8(pathName);
_writablePath += "\\";
_writablePath += Str::WideToUtf8(L"Testing");
_writablePath += "\\";
CreateDirectory(_C(Str::Utf8ToWide(_writablePath)), nullptr);
}
void Utils::ExitSdlLoop()
{
SDL_Event event = {};

View File

@ -5,6 +5,9 @@ namespace verus
class Utils : public Singleton<Utils>
{
Random _random;
String _modulePath;
String _shaderPath;
String _writablePath;
PBaseAllocator _pAllocator;
public:
@ -16,6 +19,14 @@ namespace verus
//! Destruct Utils using the provided allocator:
static void FreeEx(PBaseAllocator pAlloc);
void InitPaths();
Str GetModulePath() const { return _C(_modulePath); }
void SetModulePath(CSZ path) { _modulePath = path; }
Str GetShaderPath() const { return _C(_shaderPath); }
void SetShaderPath(CSZ path) { _shaderPath = path; }
Str GetWritablePath() const { return _C(_writablePath); }
void SetWritablePath(CSZ path) { _writablePath = path; }
RRandom GetRandom() { return _random; }
// System-wide allocator:

View File

@ -3,6 +3,9 @@
using namespace verus;
using namespace verus::IO;
CSZ FileSystem::s_dataFolder = "/Data/";
CSZ FileSystem::s_shaderPAK = "[Shaders]:";
FileSystem::FileSystem()
{
}
@ -11,14 +14,16 @@ FileSystem::~FileSystem()
{
}
size_t FileSystem::FindColonForPAK(CSZ url)
size_t FileSystem::FindPosForPAK(CSZ url)
{
const char* pColon = strchr(url, ':');
if (!pColon)
if (!url)
return String::npos;
const size_t at = pColon - url;
if (at < 2) // "C:\..."
if (*url != '[')
return String::npos;
const char* pEnd = strstr(url, "]:");
if (!pEnd)
return String::npos;
const size_t at = pEnd - url;
return at;
}
@ -37,7 +42,7 @@ void FileSystem::ReadHeaderPAK(RFile file, UINT32& magic, INT64& entriesOffset,
void FileSystem::PreloadCache(CSZ pak, CSZ types[])
{
StringStream ss;
//ss << Utils::I().GetModulePath() << "/Data/" << pak;
//ss << Utils::I().GetModulePath() << s_dataFolder << pak;
File file;
if (!file.Open(_C(ss.str())))
return;
@ -109,49 +114,48 @@ void FileSystem::PreloadCache(CSZ pak, CSZ types[])
void FileSystem::LoadResource(CSZ url, Vector<BYTE>& vData, RcLoadDesc desc)
{
String pathNamePAK, pakEntry;
const size_t colon = FindColonForPAK(url);
if (colon != String::npos) // "Foo:Bar.ext" format -> in PAK file:
const size_t pakPos = FindPosForPAK(url);
if (pakPos != String::npos) // "[Foo]:Bar.ext" format -> in PAK file:
{
String strUrl(url);
StringStream ss;
//ss << Utils::I().GetModulePath() << "/Data/";
ss << strUrl.substr(0, colon) << ".pak";
const String name = strUrl.substr(colon + 1);
ss << _C(Utils::I().GetModulePath()) << s_dataFolder;
ss << strUrl.substr(1, pakPos - 1) << ".pak";
const String name = strUrl.substr(pakPos + 2);
const WideString wide = Str::Utf8ToWide(name);
pathNamePAK = ss.str();
pakEntry = Str::CyrillicWideToAnsi(_C(wide));
}
File arPAK;
File filePAK;
if (pathNamePAK.empty() || pakEntry.empty()) // System file name?
return LoadResourceFromFile(url, vData, desc);
if (!arPAK.Open(_C(pathNamePAK))) // PAK not found? Try system file.
if (!filePAK.Open(_C(pathNamePAK))) // PAK not found? Try system file.
return LoadResourceFromFile(url, vData, desc);
LoadResourceFromPAK(url, vData, desc, arPAK, _C(pakEntry));
LoadResourceFromPAK(url, vData, desc, filePAK, _C(pakEntry));
}
void FileSystem::LoadResourceFromFile(CSZ url, Vector<BYTE>& vData, RcLoadDesc desc)
{
String strUrl(url), pathNameProject(url);
const bool shader = strUrl.find("Shaders:") != String::npos;
const size_t colon = FindColonForPAK(url);
if (colon != String::npos)
const bool shader = Str::StartsWith(url, s_shaderPAK);
const size_t pakPos = FindPosForPAK(url);
if (pakPos != String::npos)
{
if (shader/* && !Utils::I().GetForcedCgPath().empty()*/)
if (shader)
{
strUrl.replace(0, 8, "/");
strUrl.replace(0, strlen(s_shaderPAK), "/");
StringStream ss;
//ss << Utils::I().GetForcedCgPath() << strUrl;
//pathNameProject = String(_C(Utils::I().GetProjectPath())) + "/" + strUrl;
ss << _C(Utils::I().GetShaderPath()) << strUrl;
strUrl = ss.str();
}
else
{
strUrl.replace(colon, 1, "/");
String folder = strUrl.substr(1, pakPos - 1);
strUrl.replace(pakPos, 1, "/");
StringStream ss;
//ss << Utils::I().GetModulePath() << "/Data/" << strUrl;
//pathNameProject = String(_C(Utils::I().GetProjectPath())) + "/" + strUrl;
ss << _C(Utils::I().GetModulePath()) << s_dataFolder << folder << strUrl;
strUrl = ss.str();
}
}
@ -346,18 +350,18 @@ String FileSystem::ConvertFilenameToPassword(CSZ fileEntry)
bool FileSystem::FileExist(CSZ url)
{
String path(url), pak, project;
const size_t colon = FindColonForPAK(url);
if (colon != String::npos)
const size_t pakPos = FindPosForPAK(url);
if (pakPos != String::npos)
{
StringStream ssPak;
//ssPak << Utils::I().GetModulePath() << "/Data/" << path.substr(0, colon) << ".pak";
//ssPak << Utils::I().GetModulePath() << s_dataFolder << path.substr(0, pakPos) << ".pak";
pak = ssPak.str();
path.replace(colon, 1, "/");
path.replace(pakPos, 1, "/");
//project = String(_C(Utils::I().GetProjectPath())) + "/" + path;
StringStream ss;
//ss << Utils::I().GetModulePath() << "/Data/" << path;
//ss << Utils::I().GetModulePath() << s_dataFolder << path;
path = ss.str();
}
File file;
@ -411,7 +415,7 @@ String FileSystem::ConvertRelativePathToAbsolute(RcString path, bool useProjectD
//if (useProjectDir && *_C(utils.GetProjectPath()))
// systemPath = String(_C(utils.GetProjectPath())) + "/" + systemPath;
//else
// systemPath = utils.GetModulePath() + "/Data/" + systemPath;
// systemPath = utils.GetModulePath() + s_dataFolder + systemPath;
return systemPath;
}

View File

@ -8,6 +8,9 @@ namespace verus
{
typedef Map<String, Vector<BYTE>> TMapCache;
static CSZ s_dataFolder;
static CSZ s_shaderPAK;
TMapCache _mapCache;
INT64 _cacheSize = 0;
@ -29,7 +32,7 @@ namespace verus
FileSystem();
~FileSystem();
static size_t FindColonForPAK(CSZ url);
static size_t FindPosForPAK(CSZ url);
static void ReadHeaderPAK(RFile file, UINT32& magic, INT64& entriesOffset, INT64& entriesSize);
void PreloadCache(CSZ pak, CSZ types[]);

View File

@ -49,7 +49,7 @@ void KeyMapper::Done()
bool KeyMapper::HandleSdlEvent(SDL_Event& event)
{
VERUS_RT_ASSERT(IsInitialized());
//VERUS_QREF_CONST_SETTINGS;
VERUS_QREF_CONST_SETTINGS;
static bool firstTime = true;
@ -58,7 +58,7 @@ bool KeyMapper::HandleSdlEvent(SDL_Event& event)
// Keyboard:
case SDL_KEYDOWN:
{
//if (settings.m_screenWindowed && SDL_SCANCODE_KP_ENTER == event.key.keysym.scancode)
if (settings._screenWindowed && SDL_SCANCODE_KP_ENTER == event.key.keysym.scancode)
{
const SDL_bool rel = SDL_GetRelativeMouseMode();
SDL_SetRelativeMouseMode(rel ? SDL_FALSE : SDL_TRUE);

View File

@ -108,24 +108,25 @@ namespace verus
void ResetClickState();
VERUS_P(void OnKeyDown(int id));
VERUS_P(void OnKeyUp(int id));
VERUS_P(void OnChar(wchar_t c));
VERUS_P(void OnMouseMove(int x, int y));
VERUS_P(void OnMouseDown(int id));
VERUS_P(void OnMouseUp(int id));
VERUS_P(void OnMouseDoubleClick(int id));
VERUS_P(void OnJoyAxis(int id, int value));
VERUS_P(void OnJoyDown(int id));
VERUS_P(void OnJoyUp(int id));
VERUS_P(void TranslateJoy(int id, bool up));
VERUS_P(bool TranslateJoyPress(int id, bool mouse) const);
PKeyMapperDelegate SetDelegate(PKeyMapperDelegate p) { return Utils::Swap(_pKeyMapperDelegate, p); }
static CSZ GetSingletonFailMessage() { return "Make_Input(); // FAIL.\r\n"; }
private:
void OnKeyDown(int id);
void OnKeyUp(int id);
void OnChar(wchar_t c);
void OnMouseMove(int x, int y);
void OnMouseDown(int id);
void OnMouseUp(int id);
void OnMouseDoubleClick(int id);
void OnJoyAxis(int id, int value);
void OnJoyDown(int id);
void OnJoyUp(int id);
void TranslateJoy(int id, bool up);
bool TranslateJoyPress(int id, bool mouse) const;
};
VERUS_TYPEDEFS(KeyMapper);
}

View File

@ -21,6 +21,9 @@ namespace verus
yes
};
typedef glm::vec2 float2;
typedef glm::vec3 float3;
typedef glm::vec4 float4;
typedef glm::mat4 matrix;
typedef glm::mat3x4 mataff;

View File

@ -168,16 +168,4 @@ namespace verus
Point3& FromString(CSZ sz);
};
VERUS_TYPEDEFS(Point3);
class float4 : public glm::vec4
{
public:
float4() {}
float4(float s) : glm::vec4(s, 0, 0, 0) {}
float4(const glm::vec4& v) : glm::vec4(v) {}
float4(const glm::vec3& v) : glm::vec4(v, 0) {}
float4(RcVector3 v) : glm::vec4(v.GLM(), 0) {}
float4(RcVector4 v) : glm::vec4(v.GLM()) {}
float4(RcPoint3 v) : glm::vec4(v.GLM(), 0) {}
};
}

View File

@ -134,7 +134,7 @@ void Camera::LoadState(int slot)
void MainCamera::operator=(RcMainCamera that)
{
Camera::operator=(that);
_currentFrame = -1;
_currentFrame = UINT64_MAX;
}
void MainCamera::Update()
@ -149,11 +149,11 @@ void MainCamera::Update()
void MainCamera::UpdateVP()
{
//VERUS_QREF_RENDER;
//if (m_currentFrame != render.GetNumFrames())
VERUS_QREF_RENDERER;
if (_currentFrame != renderer.GetNumFrames())
{
_matPrevVP = GetMatrixVP();
//m_currentFrame = render.GetNumFrames();
_currentFrame = renderer.GetNumFrames();
}
Camera::UpdateVP();
}

View File

@ -101,7 +101,7 @@ namespace verus
{
Matrix4 _matPrevVP = Matrix4::identity(); // For motion blur.
PCursorPosProvider _pCpp = nullptr;
UINT32 _currentFrame = -1;
UINT64 _currentFrame = UINT64_MAX;
public:
void operator=(const MainCamera& that);

Binary file not shown.

View File

@ -18,9 +18,17 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
typedef const char* CSZ;
bool g_init = false;
std::string g_ret;
std::vector<unsigned int> g_vSpirv;
struct ShaderInclude
{
public:
virtual void Open(CSZ filename, void** ppData, UINT32* pBytes) = 0;
virtual void Close(void* pData) = 0;
};
bool g_init = false;
thread_local ShaderInclude* g_pShaderInclude = nullptr;
thread_local std::string g_ret;
thread_local std::vector<unsigned int> g_vSpirv;
class MyIncluder : public glslang::TShader::Includer
{
@ -33,7 +41,10 @@ public:
CSZ includerName,
size_t inclusionDepth) override
{
return nullptr;
void* pData = nullptr;
UINT32 size = 0;
g_pShaderInclude->Open(headerName, &pData, &size);
return new IncludeResult(headerName, static_cast<CSZ>(pData), size, pData);
}
virtual IncludeResult* includeLocal(
@ -41,11 +52,19 @@ public:
CSZ includerName,
size_t inclusionDepth) override
{
return nullptr;
void* pData = nullptr;
UINT32 size = 0;
g_pShaderInclude->Open(headerName, &pData, &size);
return new IncludeResult(headerName, static_cast<CSZ>(pData), size, pData);
}
virtual void releaseInclude(IncludeResult* result) override
{
if (result)
{
g_pShaderInclude->Close(result->userData);
delete result;
}
}
};
@ -69,7 +88,7 @@ extern "C"
}
}
VERUS_DLL_EXPORT bool VerusCompile(CSZ source, CSZ* defines, CSZ entryPoint, CSZ target, UINT32 flags, UINT32** ppCode, UINT32* pSize, CSZ* ppErrorMsgs)
VERUS_DLL_EXPORT bool VerusCompile(CSZ source, CSZ* defines, ShaderInclude* pInclude, CSZ entryPoint, CSZ target, UINT32 flags, UINT32** ppCode, UINT32* pSize, CSZ* ppErrorMsgs)
{
if (!g_init)
{
@ -78,6 +97,18 @@ extern "C"
return false;
}
struct RAII
{
~RAII()
{
g_pShaderInclude = nullptr;
}
} raii;
g_pShaderInclude = pInclude;
*ppCode = nullptr;
*pSize = 0;
g_ret.clear();
g_vSpirv.clear();
std::stringstream ss;
@ -110,30 +141,22 @@ extern "C"
}
std::string preamble = ssDefines.str();
const int clientInputSemanticsVersion = 100;
const int defaultVersion = 110;
glslang::TShader shader(stage);
shader.setStrings(&source, 1);
shader.setPreamble(preamble.c_str());
shader.setEntryPoint(entryPoint);
shader.setEnvInput(glslang::EShSourceHlsl, stage, glslang::EShClientVulkan, 100);
shader.setEnvInput(glslang::EShSourceHlsl, stage, glslang::EShClientVulkan, clientInputSemanticsVersion);
shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0);
shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
const TBuiltInResource builtInResources = glslang::DefaultTBuiltInResource;
const EShMessages messages = static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules);
std::string preprocessed;
const EShMessages messages = static_cast<EShMessages>(EShMsgSpvRules | EShMsgVulkanRules | EShMsgReadHlsl);
MyIncluder includer;
if (!shader.preprocess(&builtInResources, 450, ENoProfile, false, false, messages, &preprocessed, includer))
{
ss << "preprocess(), " << shader.getInfoLog() << shader.getInfoDebugLog();
g_ret = ss.str();
*ppErrorMsgs = g_ret.c_str();
return false;
}
CSZ pPreprocessed = preprocessed.c_str();
shader.setStrings(&pPreprocessed, 1);
if (!shader.parse(&builtInResources, 450, false, messages))
if (!shader.parse(&builtInResources, defaultVersion, false, messages, includer))
{
ss << "parse(), " << shader.getInfoLog() << shader.getInfoDebugLog();
g_ret = ss.str();
@ -151,12 +174,40 @@ extern "C"
return false;
}
if (!program.mapIO())
{
ss << "mapIO(), " << shader.getInfoLog() << shader.getInfoDebugLog();
g_ret = ss.str();
*ppErrorMsgs = g_ret.c_str();
return false;
}
spv::SpvBuildLogger logger;
glslang::SpvOptions options;
if (flags & 0x1)
{
options.generateDebugInfo = true;
options.disableOptimizer = true;
options.optimizeSize = false;
}
else
{
options.generateDebugInfo = false;
options.disableOptimizer = false;
options.optimizeSize = true;
}
glslang::GlslangToSpv(*program.getIntermediate(stage), g_vSpirv, &logger, &options);
const unsigned int magicNumber = 0x07230203;
if (g_vSpirv[0] != magicNumber)
{
g_ret = "magicNumber";
*ppErrorMsgs = g_ret.c_str();
return false;
}
*ppCode = g_vSpirv.data();
*pSize = static_cast<UINT32>(g_vSpirv.size());
*pSize = static_cast<UINT32>(g_vSpirv.size() * sizeof(unsigned int));
return true;
}