2019.6
This commit is contained in:
parent
37436a8de2
commit
90309c7a43
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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=?";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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
|
@ -3,4 +3,5 @@
|
|||
#define VERUS_INCLUDE_D3D12
|
||||
#include <verus.h>
|
||||
|
||||
#include "d3dx12.h"
|
||||
#include "CGI/CGI.h"
|
||||
|
|
|
@ -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()];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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, ©Region);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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=?";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Damping.h"
|
||||
#include "Motion.h"
|
||||
#include "Skeleton.h"
|
||||
#include "Animation.h"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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()) &&
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ namespace verus
|
|||
|
||||
class BaseShader : public Object
|
||||
{
|
||||
static CSZ s_branchCommentMarker;
|
||||
|
||||
public:
|
||||
enum class Stage : int
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace verus
|
|||
|
||||
// Internal objects:
|
||||
Scene::RCamera GetCamera();
|
||||
//RCharacter GetCameraCharacter();
|
||||
RSpirit GetCameraSpirit();
|
||||
|
||||
// Configurations:
|
||||
void ActivateDefaultCameraMovement(bool b);
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
|
||||
#include "State.h"
|
||||
#include "StateMachine.h"
|
||||
#include "Spirit.h"
|
||||
#include "BaseGame.h"
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -20,6 +20,10 @@ void State::Update()
|
|||
{
|
||||
}
|
||||
|
||||
void State::Draw()
|
||||
{
|
||||
}
|
||||
|
||||
void State::OnExit(PState pNext)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 = {};
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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[]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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) {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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.
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue