Ajout de Jolt Physics + 1ere version des factory entitecomposants - camera, transform, rigidbody, collider, renderer
This commit is contained in:
21
lib/All/JoltPhysics/TestFramework/Renderer/VK/BufferVK.h
Normal file
21
lib/All/JoltPhysics/TestFramework/Renderer/VK/BufferVK.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
/// Simple wrapper class to manage a Vulkan buffer
|
||||
class BufferVK
|
||||
{
|
||||
public:
|
||||
VkBuffer mBuffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory mMemory = VK_NULL_HANDLE;
|
||||
VkDeviceSize mOffset = 0;
|
||||
VkDeviceSize mSize = 0;
|
||||
|
||||
VkBufferUsageFlags mUsage;
|
||||
VkMemoryPropertyFlags mProperties;
|
||||
VkDeviceSize mAllocatedSize;
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Renderer/VK/ConstantBufferVK.h>
|
||||
#include <Renderer/VK/RendererVK.h>
|
||||
#include <Renderer/VK/FatalErrorIfFailedVK.h>
|
||||
|
||||
ConstantBufferVK::ConstantBufferVK(RendererVK *inRenderer, VkDeviceSize inBufferSize) :
|
||||
mRenderer(inRenderer)
|
||||
{
|
||||
mRenderer->CreateBuffer(inBufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, mBuffer);
|
||||
}
|
||||
|
||||
ConstantBufferVK::~ConstantBufferVK()
|
||||
{
|
||||
mRenderer->FreeBuffer(mBuffer);
|
||||
}
|
||||
|
||||
void *ConstantBufferVK::MapInternal()
|
||||
{
|
||||
void *data = nullptr;
|
||||
FatalErrorIfFailed(vkMapMemory(mRenderer->GetDevice(), mBuffer.mMemory, mBuffer.mOffset, mBuffer.mSize, 0, &data));
|
||||
return data;
|
||||
}
|
||||
|
||||
void ConstantBufferVK::Unmap()
|
||||
{
|
||||
vkUnmapMemory(mRenderer->GetDevice(), mBuffer.mMemory);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Renderer/VK/BufferVK.h>
|
||||
|
||||
class RendererVK;
|
||||
|
||||
/// A binary blob that can be used to pass constants to a shader
|
||||
class ConstantBufferVK
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
ConstantBufferVK(RendererVK *inRenderer, VkDeviceSize inBufferSize);
|
||||
~ConstantBufferVK();
|
||||
|
||||
/// Map / unmap buffer (get pointer to data). This will discard all data in the buffer.
|
||||
template <typename T> T * Map() { return reinterpret_cast<T *>(MapInternal()); }
|
||||
void Unmap();
|
||||
|
||||
VkBuffer GetBuffer() const { return mBuffer.mBuffer; }
|
||||
|
||||
private:
|
||||
void * MapInternal();
|
||||
|
||||
RendererVK * mRenderer;
|
||||
BufferVK mBuffer;
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Renderer/VK/FatalErrorIfFailedVK.h>
|
||||
#include <Utils/Log.h>
|
||||
|
||||
void FatalErrorIfFailed(VkResult inVkResult)
|
||||
{
|
||||
if (inVkResult != VK_SUCCESS)
|
||||
FatalError("Vulkan error returned: %d", inVkResult);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
/// Convert Vulkan error to readable text and alert
|
||||
void FatalErrorIfFailed(VkResult inVkResult);
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Renderer/VK/PipelineStateVK.h>
|
||||
#include <Renderer/VK/RendererVK.h>
|
||||
#include <Renderer/VK/FatalErrorIfFailedVK.h>
|
||||
|
||||
PipelineStateVK::PipelineStateVK(RendererVK *inRenderer, const VertexShaderVK *inVertexShader, const EInputDescription *inInputDescription, uint inInputDescriptionCount, const PixelShaderVK *inPixelShader, EDrawPass inDrawPass, EFillMode inFillMode, ETopology inTopology, EDepthTest inDepthTest, EBlendMode inBlendMode, ECullMode inCullMode) :
|
||||
mRenderer(inRenderer),
|
||||
mVertexShader(inVertexShader),
|
||||
mPixelShader(inPixelShader)
|
||||
{
|
||||
VkPipelineShaderStageCreateInfo shader_stages[] = { inVertexShader->mStageInfo, inPixelShader->mStageInfo };
|
||||
|
||||
// TODO: This doesn't follow the SPIR-V alignment rules
|
||||
Array<VkVertexInputAttributeDescription> attribute_descriptions;
|
||||
VkVertexInputAttributeDescription temp_vtx = { }, temp_instance = { };
|
||||
temp_instance.binding = 1;
|
||||
uint instance_alignment = 1;
|
||||
for (uint i = 0; i < inInputDescriptionCount; ++i)
|
||||
switch (inInputDescription[i])
|
||||
{
|
||||
case EInputDescription::Position:
|
||||
case EInputDescription::Normal:
|
||||
temp_vtx.format = VK_FORMAT_R32G32B32_SFLOAT;
|
||||
attribute_descriptions.push_back(temp_vtx);
|
||||
temp_vtx.offset += 3 * sizeof(float);
|
||||
break;
|
||||
|
||||
case EInputDescription::Color:
|
||||
temp_vtx.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
attribute_descriptions.push_back(temp_vtx);
|
||||
temp_vtx.offset += 4 * sizeof(uint8);
|
||||
break;
|
||||
|
||||
case EInputDescription::TexCoord:
|
||||
temp_vtx.format = VK_FORMAT_R32G32_SFLOAT;
|
||||
attribute_descriptions.push_back(temp_vtx);
|
||||
temp_vtx.offset += 2 * sizeof(float);
|
||||
break;
|
||||
|
||||
case EInputDescription::InstanceColor:
|
||||
instance_alignment = max(instance_alignment, 4u);
|
||||
temp_instance.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
attribute_descriptions.push_back(temp_instance);
|
||||
temp_instance.offset += 4 * sizeof(uint8);
|
||||
break;
|
||||
|
||||
case EInputDescription::InstanceTransform:
|
||||
case EInputDescription::InstanceInvTransform:
|
||||
instance_alignment = max(instance_alignment, 16u);
|
||||
temp_instance.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
attribute_descriptions.push_back(temp_instance);
|
||||
temp_instance.offset += 4 * sizeof(float);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < uint32(attribute_descriptions.size()); ++i)
|
||||
attribute_descriptions[i].location = i;
|
||||
|
||||
VkVertexInputBindingDescription binding_description[2];
|
||||
binding_description[0].binding = 0;
|
||||
binding_description[0].stride = temp_vtx.offset;
|
||||
binding_description[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||
binding_description[1].binding = 1;
|
||||
binding_description[1].stride = AlignUp(temp_instance.offset, instance_alignment);
|
||||
binding_description[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
|
||||
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
vertex_input_info.vertexBindingDescriptionCount = temp_instance.offset > 0? 2 : 1;
|
||||
vertex_input_info.pVertexBindingDescriptions = binding_description;
|
||||
vertex_input_info.vertexAttributeDescriptionCount = uint32(attribute_descriptions.size());
|
||||
vertex_input_info.pVertexAttributeDescriptions = attribute_descriptions.data();
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo input_assembly = {};
|
||||
input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
input_assembly.topology = inTopology == ETopology::Triangle? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST : VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
||||
input_assembly.primitiveRestartEnable = VK_FALSE;
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewport_state = {};
|
||||
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
viewport_state.viewportCount = 1;
|
||||
viewport_state.scissorCount = 1;
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo rasterizer = {};
|
||||
rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
rasterizer.depthClampEnable = VK_FALSE;
|
||||
rasterizer.rasterizerDiscardEnable = VK_FALSE;
|
||||
rasterizer.polygonMode = inFillMode == EFillMode::Solid? VK_POLYGON_MODE_FILL : VK_POLYGON_MODE_LINE;
|
||||
rasterizer.lineWidth = 1.0f;
|
||||
rasterizer.cullMode = inCullMode == ECullMode::Backface? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT;
|
||||
rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
rasterizer.depthBiasEnable = VK_FALSE;
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisampling = {};
|
||||
multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
multisampling.sampleShadingEnable = VK_FALSE;
|
||||
multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
VkPipelineDepthStencilStateCreateInfo depth_stencil = {};
|
||||
depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||
depth_stencil.depthTestEnable = inDepthTest == EDepthTest::On? VK_TRUE : VK_FALSE;
|
||||
depth_stencil.depthWriteEnable = inDepthTest == EDepthTest::On? VK_TRUE : VK_FALSE;
|
||||
depth_stencil.depthCompareOp = VK_COMPARE_OP_GREATER_OR_EQUAL; // Reverse-Z, greater is closer
|
||||
|
||||
VkPipelineColorBlendAttachmentState color_blend_attachment = {};
|
||||
color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
switch (inBlendMode)
|
||||
{
|
||||
case EBlendMode::Write:
|
||||
color_blend_attachment.blendEnable = VK_FALSE;
|
||||
break;
|
||||
|
||||
case EBlendMode::AlphaBlend:
|
||||
color_blend_attachment.blendEnable = VK_TRUE;
|
||||
color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
color_blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
break;
|
||||
}
|
||||
|
||||
VkPipelineColorBlendStateCreateInfo color_blending = {};
|
||||
color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
color_blending.logicOpEnable = VK_FALSE;
|
||||
color_blending.logicOp = VK_LOGIC_OP_COPY;
|
||||
color_blending.attachmentCount = 1;
|
||||
color_blending.pAttachments = &color_blend_attachment;
|
||||
|
||||
VkDynamicState dynamic_states[] = {
|
||||
VK_DYNAMIC_STATE_VIEWPORT,
|
||||
VK_DYNAMIC_STATE_SCISSOR
|
||||
};
|
||||
VkPipelineDynamicStateCreateInfo dynamic_state = {};
|
||||
dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
dynamic_state.dynamicStateCount = std::size(dynamic_states);
|
||||
dynamic_state.pDynamicStates = dynamic_states;
|
||||
|
||||
VkGraphicsPipelineCreateInfo pipeline_info = {};
|
||||
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||
pipeline_info.stageCount = std::size(shader_stages);
|
||||
pipeline_info.pStages = shader_stages;
|
||||
pipeline_info.pVertexInputState = &vertex_input_info;
|
||||
pipeline_info.pInputAssemblyState = &input_assembly;
|
||||
pipeline_info.pViewportState = &viewport_state;
|
||||
pipeline_info.pRasterizationState = &rasterizer;
|
||||
pipeline_info.pMultisampleState = &multisampling;
|
||||
pipeline_info.pDepthStencilState = &depth_stencil;
|
||||
pipeline_info.pColorBlendState = &color_blending;
|
||||
pipeline_info.pDynamicState = &dynamic_state;
|
||||
pipeline_info.layout = mRenderer->GetPipelineLayout();
|
||||
pipeline_info.renderPass = inDrawPass == EDrawPass::Normal? mRenderer->GetRenderPass() : mRenderer->GetRenderPassShadow();
|
||||
FatalErrorIfFailed(vkCreateGraphicsPipelines(mRenderer->GetDevice(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &mGraphicsPipeline));
|
||||
}
|
||||
|
||||
PipelineStateVK::~PipelineStateVK()
|
||||
{
|
||||
vkDeviceWaitIdle(mRenderer->GetDevice());
|
||||
|
||||
vkDestroyPipeline(mRenderer->GetDevice(), mGraphicsPipeline, nullptr);
|
||||
}
|
||||
|
||||
void PipelineStateVK::Activate()
|
||||
{
|
||||
vkCmdBindPipeline(mRenderer->GetCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, mGraphicsPipeline);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Renderer/PipelineState.h>
|
||||
#include <Renderer/VK/VertexShaderVK.h>
|
||||
#include <Renderer/VK/PixelShaderVK.h>
|
||||
|
||||
class RendererVK;
|
||||
|
||||
/// Vulkan pipeline state object
|
||||
class PipelineStateVK : public PipelineState
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
PipelineStateVK(RendererVK *inRenderer, const VertexShaderVK *inVertexShader, const EInputDescription *inInputDescription, uint inInputDescriptionCount, const PixelShaderVK *inPixelShader, EDrawPass inDrawPass, EFillMode inFillMode, ETopology inTopology, EDepthTest inDepthTest, EBlendMode inBlendMode, ECullMode inCullMode);
|
||||
virtual ~PipelineStateVK() override;
|
||||
|
||||
/// Make this pipeline state active (any primitives rendered after this will use this state)
|
||||
virtual void Activate() override;
|
||||
|
||||
private:
|
||||
RendererVK * mRenderer;
|
||||
RefConst<VertexShaderVK> mVertexShader;
|
||||
RefConst<PixelShaderVK> mPixelShader;
|
||||
|
||||
VkPipeline mGraphicsPipeline;
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Renderer/PixelShader.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
/// Pixel shader handle for Vulkan
|
||||
class PixelShaderVK : public PixelShader
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
PixelShaderVK(VkDevice inDevice, VkShaderModule inShaderModule) :
|
||||
mDevice(inDevice),
|
||||
mStageInfo()
|
||||
{
|
||||
mStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
mStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
mStageInfo.module = inShaderModule;
|
||||
mStageInfo.pName = "main";
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~PixelShaderVK() override
|
||||
{
|
||||
vkDestroyShaderModule(mDevice, mStageInfo.module, nullptr);
|
||||
}
|
||||
|
||||
VkDevice mDevice;
|
||||
VkPipelineShaderStageCreateInfo mStageInfo;
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Renderer/VK/RenderInstancesVK.h>
|
||||
#include <Renderer/VK/RenderPrimitiveVK.h>
|
||||
#include <Renderer/VK/FatalErrorIfFailedVK.h>
|
||||
|
||||
void RenderInstancesVK::Clear()
|
||||
{
|
||||
mRenderer->FreeBuffer(mInstancesBuffer);
|
||||
}
|
||||
|
||||
void RenderInstancesVK::CreateBuffer(int inNumInstances, int inInstanceSize)
|
||||
{
|
||||
Clear();
|
||||
|
||||
mRenderer->CreateBuffer(VkDeviceSize(inNumInstances) * inInstanceSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, mInstancesBuffer);
|
||||
}
|
||||
|
||||
void *RenderInstancesVK::Lock()
|
||||
{
|
||||
void *data;
|
||||
FatalErrorIfFailed(vkMapMemory(mRenderer->GetDevice(), mInstancesBuffer.mMemory, mInstancesBuffer.mOffset, mInstancesBuffer.mSize, 0, &data));
|
||||
return data;
|
||||
}
|
||||
|
||||
void RenderInstancesVK::Unlock()
|
||||
{
|
||||
vkUnmapMemory(mRenderer->GetDevice(), mInstancesBuffer.mMemory);
|
||||
}
|
||||
|
||||
void RenderInstancesVK::Draw(RenderPrimitive *inPrimitive, int inStartInstance, int inNumInstances) const
|
||||
{
|
||||
if (inNumInstances <= 0)
|
||||
return;
|
||||
|
||||
VkCommandBuffer command_buffer = mRenderer->GetCommandBuffer();
|
||||
RenderPrimitiveVK *primitive = static_cast<RenderPrimitiveVK *>(inPrimitive);
|
||||
|
||||
VkBuffer buffers[] = { primitive->mVertexBuffer.mBuffer, mInstancesBuffer.mBuffer };
|
||||
VkDeviceSize offsets[] = { 0, 0 };
|
||||
vkCmdBindVertexBuffers(command_buffer, 0, 2, buffers, offsets);
|
||||
|
||||
if (primitive->mIndexBuffer.mBuffer == VK_NULL_HANDLE)
|
||||
{
|
||||
vkCmdDraw(command_buffer, primitive->mNumVtxToDraw, inNumInstances, 0, inStartInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
vkCmdBindIndexBuffer(command_buffer, primitive->mIndexBuffer.mBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
vkCmdDrawIndexed(command_buffer, primitive->mNumIdxToDraw, inNumInstances, 0, 0, inStartInstance);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Renderer/VK/RendererVK.h>
|
||||
#include <Renderer/RenderInstances.h>
|
||||
|
||||
class RenderPrimitive;
|
||||
|
||||
/// Vulkan implementation of a render instances object
|
||||
class RenderInstancesVK : public RenderInstances
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
RenderInstancesVK(RendererVK *inRenderer) : mRenderer(inRenderer) { }
|
||||
virtual ~RenderInstancesVK() override { Clear(); }
|
||||
|
||||
/// Erase all instance data
|
||||
virtual void Clear() override;
|
||||
|
||||
/// Instance buffer management functions
|
||||
virtual void CreateBuffer(int inNumInstances, int inInstanceSize) override;
|
||||
virtual void * Lock() override;
|
||||
virtual void Unlock() override;
|
||||
|
||||
/// Draw the instances when context has been set by Renderer::BindShader
|
||||
virtual void Draw(RenderPrimitive *inPrimitive, int inStartInstance, int inNumInstances) const override;
|
||||
|
||||
private:
|
||||
RendererVK * mRenderer;
|
||||
|
||||
BufferVK mInstancesBuffer;
|
||||
};
|
||||
@@ -0,0 +1,100 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Renderer/VK/RenderPrimitiveVK.h>
|
||||
#include <Renderer/VK/FatalErrorIfFailedVK.h>
|
||||
|
||||
void RenderPrimitiveVK::ReleaseVertexBuffer()
|
||||
{
|
||||
mRenderer->FreeBuffer(mVertexBuffer);
|
||||
mVertexBufferDeviceLocal = false;
|
||||
|
||||
RenderPrimitive::ReleaseVertexBuffer();
|
||||
}
|
||||
|
||||
void RenderPrimitiveVK::ReleaseIndexBuffer()
|
||||
{
|
||||
mRenderer->FreeBuffer(mIndexBuffer);
|
||||
mIndexBufferDeviceLocal = false;
|
||||
|
||||
RenderPrimitive::ReleaseIndexBuffer();
|
||||
}
|
||||
|
||||
void RenderPrimitiveVK::CreateVertexBuffer(int inNumVtx, int inVtxSize, const void *inData)
|
||||
{
|
||||
RenderPrimitive::CreateVertexBuffer(inNumVtx, inVtxSize, inData);
|
||||
|
||||
VkDeviceSize size = VkDeviceSize(inNumVtx) * inVtxSize;
|
||||
if (inData != nullptr)
|
||||
{
|
||||
mRenderer->CreateDeviceLocalBuffer(inData, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, mVertexBuffer);
|
||||
mVertexBufferDeviceLocal = true;
|
||||
}
|
||||
else
|
||||
mRenderer->CreateBuffer(size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, mVertexBuffer);
|
||||
}
|
||||
|
||||
void *RenderPrimitiveVK::LockVertexBuffer()
|
||||
{
|
||||
JPH_ASSERT(!mVertexBufferDeviceLocal);
|
||||
|
||||
void *data;
|
||||
FatalErrorIfFailed(vkMapMemory(mRenderer->GetDevice(), mVertexBuffer.mMemory, mVertexBuffer.mOffset, VkDeviceSize(mNumVtx) * mVtxSize, 0, &data));
|
||||
return data;
|
||||
}
|
||||
|
||||
void RenderPrimitiveVK::UnlockVertexBuffer()
|
||||
{
|
||||
vkUnmapMemory(mRenderer->GetDevice(), mVertexBuffer.mMemory);
|
||||
}
|
||||
|
||||
void RenderPrimitiveVK::CreateIndexBuffer(int inNumIdx, const uint32 *inData)
|
||||
{
|
||||
RenderPrimitive::CreateIndexBuffer(inNumIdx, inData);
|
||||
|
||||
VkDeviceSize size = VkDeviceSize(inNumIdx) * sizeof(uint32);
|
||||
if (inData != nullptr)
|
||||
{
|
||||
mRenderer->CreateDeviceLocalBuffer(inData, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, mIndexBuffer);
|
||||
mIndexBufferDeviceLocal = true;
|
||||
}
|
||||
else
|
||||
mRenderer->CreateBuffer(size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, mIndexBuffer);
|
||||
}
|
||||
|
||||
uint32 *RenderPrimitiveVK::LockIndexBuffer()
|
||||
{
|
||||
JPH_ASSERT(!mIndexBufferDeviceLocal);
|
||||
|
||||
void *data;
|
||||
vkMapMemory(mRenderer->GetDevice(), mIndexBuffer.mMemory, mIndexBuffer.mOffset, VkDeviceSize(mNumIdx) * sizeof(uint32), 0, &data);
|
||||
return reinterpret_cast<uint32 *>(data);
|
||||
}
|
||||
|
||||
void RenderPrimitiveVK::UnlockIndexBuffer()
|
||||
{
|
||||
vkUnmapMemory(mRenderer->GetDevice(), mIndexBuffer.mMemory);
|
||||
}
|
||||
|
||||
void RenderPrimitiveVK::Draw() const
|
||||
{
|
||||
VkCommandBuffer command_buffer = mRenderer->GetCommandBuffer();
|
||||
|
||||
VkBuffer vertex_buffers[] = { mVertexBuffer.mBuffer };
|
||||
VkDeviceSize offsets[] = { 0 };
|
||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
|
||||
|
||||
if (mIndexBuffer.mBuffer == VK_NULL_HANDLE)
|
||||
{
|
||||
vkCmdDraw(command_buffer, mNumVtxToDraw, 1, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
vkCmdBindIndexBuffer(command_buffer, mIndexBuffer.mBuffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
vkCmdDrawIndexed(command_buffer, mNumIdxToDraw, 1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Renderer/RenderPrimitive.h>
|
||||
#include <Renderer/VK/RendererVK.h>
|
||||
#include <Renderer/VK/BufferVK.h>
|
||||
|
||||
/// Vulkan implementation of a render primitive
|
||||
class RenderPrimitiveVK : public RenderPrimitive
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
RenderPrimitiveVK(RendererVK *inRenderer) : mRenderer(inRenderer) { }
|
||||
virtual ~RenderPrimitiveVK() override { Clear(); }
|
||||
|
||||
/// Vertex buffer management functions
|
||||
virtual void CreateVertexBuffer(int inNumVtx, int inVtxSize, const void *inData = nullptr) override;
|
||||
virtual void ReleaseVertexBuffer() override;
|
||||
virtual void * LockVertexBuffer() override;
|
||||
virtual void UnlockVertexBuffer() override;
|
||||
|
||||
/// Index buffer management functions
|
||||
virtual void CreateIndexBuffer(int inNumIdx, const uint32 *inData = nullptr) override;
|
||||
virtual void ReleaseIndexBuffer() override;
|
||||
virtual uint32 * LockIndexBuffer() override;
|
||||
virtual void UnlockIndexBuffer() override;
|
||||
|
||||
/// Draw the primitive
|
||||
virtual void Draw() const override;
|
||||
|
||||
private:
|
||||
friend class RenderInstancesVK;
|
||||
|
||||
RendererVK * mRenderer;
|
||||
|
||||
BufferVK mVertexBuffer;
|
||||
bool mVertexBufferDeviceLocal = false;
|
||||
|
||||
BufferVK mIndexBuffer;
|
||||
bool mIndexBufferDeviceLocal = false;
|
||||
};
|
||||
1324
lib/All/JoltPhysics/TestFramework/Renderer/VK/RendererVK.cpp
Normal file
1324
lib/All/JoltPhysics/TestFramework/Renderer/VK/RendererVK.cpp
Normal file
File diff suppressed because it is too large
Load Diff
156
lib/All/JoltPhysics/TestFramework/Renderer/VK/RendererVK.h
Normal file
156
lib/All/JoltPhysics/TestFramework/Renderer/VK/RendererVK.h
Normal file
@@ -0,0 +1,156 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Renderer/Renderer.h>
|
||||
#include <Renderer/VK/ConstantBufferVK.h>
|
||||
#include <Renderer/VK/TextureVK.h>
|
||||
#include <Jolt/Core/UnorderedMap.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
/// Vulkan renderer
|
||||
class RendererVK : public Renderer
|
||||
{
|
||||
public:
|
||||
/// Destructor
|
||||
virtual ~RendererVK() override;
|
||||
|
||||
// See: Renderer
|
||||
virtual void Initialize(ApplicationWindow *inWindow) override;
|
||||
virtual bool BeginFrame(const CameraState &inCamera, float inWorldScale) override;
|
||||
virtual void EndShadowPass() override;
|
||||
virtual void EndFrame() override;
|
||||
virtual void SetProjectionMode() override;
|
||||
virtual void SetOrthoMode() override;
|
||||
virtual Ref<Texture> CreateTexture(const Surface *inSurface) override;
|
||||
virtual Ref<VertexShader> CreateVertexShader(const char *inName) override;
|
||||
virtual Ref<PixelShader> CreatePixelShader(const char *inName) override;
|
||||
virtual unique_ptr<PipelineState> CreatePipelineState(const VertexShader *inVertexShader, const PipelineState::EInputDescription *inInputDescription, uint inInputDescriptionCount, const PixelShader *inPixelShader, PipelineState::EDrawPass inDrawPass, PipelineState::EFillMode inFillMode, PipelineState::ETopology inTopology, PipelineState::EDepthTest inDepthTest, PipelineState::EBlendMode inBlendMode, PipelineState::ECullMode inCullMode) override;
|
||||
virtual RenderPrimitive * CreateRenderPrimitive(PipelineState::ETopology inType) override;
|
||||
virtual RenderInstances * CreateRenderInstances() override;
|
||||
virtual Texture * GetShadowMap() const override { return mShadowMap.GetPtr(); }
|
||||
virtual void OnWindowResize() override;
|
||||
|
||||
VkDevice GetDevice() const { return mDevice; }
|
||||
VkDescriptorPool GetDescriptorPool() const { return mDescriptorPool; }
|
||||
VkDescriptorSetLayout GetDescriptorSetLayoutTexture() const { return mDescriptorSetLayoutTexture; }
|
||||
VkSampler GetTextureSamplerRepeat() const { return mTextureSamplerRepeat; }
|
||||
VkSampler GetTextureSamplerShadow() const { return mTextureSamplerShadow; }
|
||||
VkRenderPass GetRenderPassShadow() const { return mRenderPassShadow; }
|
||||
VkRenderPass GetRenderPass() const { return mRenderPass; }
|
||||
VkPipelineLayout GetPipelineLayout() const { return mPipelineLayout; }
|
||||
VkCommandBuffer GetCommandBuffer() { JPH_ASSERT(mInFrame); return mCommandBuffers[mFrameIndex]; }
|
||||
VkCommandBuffer StartTempCommandBuffer();
|
||||
void EndTempCommandBuffer(VkCommandBuffer inCommandBuffer);
|
||||
void AllocateMemory(VkDeviceSize inSize, uint32 inMemoryTypeBits, VkMemoryPropertyFlags inProperties, VkDeviceMemory &outMemory);
|
||||
void FreeMemory(VkDeviceMemory inMemory, VkDeviceSize inSize);
|
||||
void CreateBuffer(VkDeviceSize inSize, VkBufferUsageFlags inUsage, VkMemoryPropertyFlags inProperties, BufferVK &outBuffer);
|
||||
void CopyBuffer(VkBuffer inSrc, VkBuffer inDst, VkDeviceSize inSize);
|
||||
void CreateDeviceLocalBuffer(const void *inData, VkDeviceSize inSize, VkBufferUsageFlags inUsage, BufferVK &outBuffer);
|
||||
void FreeBuffer(BufferVK &ioBuffer);
|
||||
unique_ptr<ConstantBufferVK> CreateConstantBuffer(VkDeviceSize inBufferSize);
|
||||
void CreateImage(uint32 inWidth, uint32 inHeight, VkFormat inFormat, VkImageTiling inTiling, VkImageUsageFlags inUsage, VkMemoryPropertyFlags inProperties, VkImage &outImage, VkDeviceMemory &outMemory);
|
||||
void DestroyImage(VkImage inImage, VkDeviceMemory inMemory);
|
||||
VkImageView CreateImageView(VkImage inImage, VkFormat inFormat, VkImageAspectFlags inAspectFlags);
|
||||
VkFormat FindDepthFormat();
|
||||
|
||||
private:
|
||||
uint32 FindMemoryType(uint32 inTypeFilter, VkMemoryPropertyFlags inProperties);
|
||||
void FreeBufferInternal(BufferVK &ioBuffer);
|
||||
VkSurfaceFormatKHR SelectFormat(VkPhysicalDevice inDevice);
|
||||
void CreateSwapChain(VkPhysicalDevice inDevice);
|
||||
void DestroySwapChain();
|
||||
void UpdateViewPortAndScissorRect(uint32 inWidth, uint32 inHeight);
|
||||
VkSemaphore AllocateSemaphore();
|
||||
void FreeSemaphore(VkSemaphore inSemaphore);
|
||||
|
||||
VkInstance mInstance = VK_NULL_HANDLE;
|
||||
#ifdef JPH_DEBUG
|
||||
VkDebugUtilsMessengerEXT mDebugMessenger = VK_NULL_HANDLE;
|
||||
#endif
|
||||
VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
|
||||
VkPhysicalDeviceMemoryProperties mMemoryProperties;
|
||||
VkDevice mDevice = VK_NULL_HANDLE;
|
||||
uint32 mGraphicsQueueIndex = 0;
|
||||
uint32 mPresentQueueIndex = 0;
|
||||
VkQueue mGraphicsQueue = VK_NULL_HANDLE;
|
||||
VkQueue mPresentQueue = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR mSurface = VK_NULL_HANDLE;
|
||||
VkSwapchainKHR mSwapChain = VK_NULL_HANDLE;
|
||||
bool mSubOptimalSwapChain = false;
|
||||
Array<VkImage> mSwapChainImages;
|
||||
VkFormat mSwapChainImageFormat;
|
||||
VkExtent2D mSwapChainExtent;
|
||||
Array<VkImageView> mSwapChainImageViews;
|
||||
VkImage mDepthImage = VK_NULL_HANDLE;
|
||||
VkDeviceMemory mDepthImageMemory = VK_NULL_HANDLE;
|
||||
VkImageView mDepthImageView = VK_NULL_HANDLE;
|
||||
VkDescriptorSetLayout mDescriptorSetLayoutUBO = VK_NULL_HANDLE;
|
||||
VkDescriptorSetLayout mDescriptorSetLayoutTexture = VK_NULL_HANDLE;
|
||||
VkDescriptorPool mDescriptorPool = VK_NULL_HANDLE;
|
||||
VkDescriptorSet mDescriptorSets[cFrameCount];
|
||||
VkDescriptorSet mDescriptorSetsOrtho[cFrameCount];
|
||||
VkSampler mTextureSamplerShadow = VK_NULL_HANDLE;
|
||||
VkSampler mTextureSamplerRepeat = VK_NULL_HANDLE;
|
||||
VkRenderPass mRenderPassShadow = VK_NULL_HANDLE;
|
||||
VkRenderPass mRenderPass = VK_NULL_HANDLE;
|
||||
VkPipelineLayout mPipelineLayout = VK_NULL_HANDLE;
|
||||
VkFramebuffer mShadowFrameBuffer = VK_NULL_HANDLE;
|
||||
Array<VkFramebuffer> mSwapChainFramebuffers;
|
||||
uint32 mImageIndex = 0;
|
||||
VkCommandPool mCommandPool = VK_NULL_HANDLE;
|
||||
VkCommandBuffer mCommandBuffers[cFrameCount];
|
||||
Array<VkSemaphore> mAvailableSemaphores;
|
||||
Array<VkSemaphore> mImageAvailableSemaphores;
|
||||
Array<VkSemaphore> mRenderFinishedSemaphores;
|
||||
VkFence mInFlightFences[cFrameCount];
|
||||
Ref<TextureVK> mShadowMap;
|
||||
unique_ptr<ConstantBufferVK> mVertexShaderConstantBufferProjection[cFrameCount];
|
||||
unique_ptr<ConstantBufferVK> mVertexShaderConstantBufferOrtho[cFrameCount];
|
||||
unique_ptr<ConstantBufferVK> mPixelShaderConstantBuffer[cFrameCount];
|
||||
|
||||
struct Key
|
||||
{
|
||||
bool operator == (const Key &inRHS) const
|
||||
{
|
||||
return mSize == inRHS.mSize && mUsage == inRHS.mUsage && mProperties == inRHS.mProperties;
|
||||
}
|
||||
|
||||
VkDeviceSize mSize;
|
||||
VkBufferUsageFlags mUsage;
|
||||
VkMemoryPropertyFlags mProperties;
|
||||
};
|
||||
|
||||
JPH_MAKE_HASH_STRUCT(Key, KeyHasher, t.mSize, t.mUsage, t.mProperties)
|
||||
|
||||
// We try to recycle buffers from frame to frame
|
||||
using BufferCache = UnorderedMap<Key, Array<BufferVK>, KeyHasher>;
|
||||
|
||||
BufferCache mFreedBuffers[cFrameCount];
|
||||
BufferCache mBufferCache;
|
||||
|
||||
// Smaller allocations (from cMinAllocSize to cMaxAllocSize) will be done in blocks of cBlockSize bytes.
|
||||
// We do this because there is a limit to the number of allocations that we can make in Vulkan.
|
||||
static constexpr VkDeviceSize cMinAllocSize = 512;
|
||||
static constexpr VkDeviceSize cMaxAllocSize = 65536;
|
||||
static constexpr VkDeviceSize cBlockSize = 524288;
|
||||
|
||||
JPH_MAKE_HASH_STRUCT(Key, MemKeyHasher, t.mUsage, t.mProperties, t.mSize)
|
||||
|
||||
struct Memory
|
||||
{
|
||||
VkDeviceMemory mMemory;
|
||||
VkDeviceSize mOffset;
|
||||
};
|
||||
|
||||
using MemoryCache = UnorderedMap<Key, Array<Memory>, KeyHasher>;
|
||||
|
||||
MemoryCache mMemoryCache;
|
||||
uint32 mNumAllocations = 0;
|
||||
uint32 mMaxNumAllocations = 0;
|
||||
VkDeviceSize mTotalAllocated = 0;
|
||||
VkDeviceSize mMaxTotalAllocated = 0;
|
||||
};
|
||||
180
lib/All/JoltPhysics/TestFramework/Renderer/VK/TextureVK.cpp
Normal file
180
lib/All/JoltPhysics/TestFramework/Renderer/VK/TextureVK.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <TestFramework.h>
|
||||
|
||||
#include <Renderer/VK/TextureVK.h>
|
||||
#include <Renderer/VK/RendererVK.h>
|
||||
#include <Renderer/VK/FatalErrorIfFailedVK.h>
|
||||
#include <Image/BlitSurface.h>
|
||||
|
||||
TextureVK::TextureVK(RendererVK *inRenderer, const Surface *inSurface) :
|
||||
Texture(inSurface->GetWidth(), inSurface->GetHeight()),
|
||||
mRenderer(inRenderer)
|
||||
{
|
||||
ESurfaceFormat format = inSurface->GetFormat();
|
||||
VkFormat vk_format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
switch (format)
|
||||
{
|
||||
case ESurfaceFormat::A4L4: vk_format = VK_FORMAT_R8G8_UNORM; format = ESurfaceFormat::A8L8; break;
|
||||
case ESurfaceFormat::L8: vk_format = VK_FORMAT_R8_UNORM; break;
|
||||
case ESurfaceFormat::A8: vk_format = VK_FORMAT_A8_UNORM_KHR; break;
|
||||
case ESurfaceFormat::A8L8: vk_format = VK_FORMAT_R8G8_UNORM; break;
|
||||
case ESurfaceFormat::R5G6B5: vk_format = VK_FORMAT_B5G6R5_UNORM_PACK16; break;
|
||||
case ESurfaceFormat::X1R5G5B5: vk_format = VK_FORMAT_B5G5R5A1_UNORM_PACK16; format = ESurfaceFormat::A1R5G5B5; break;
|
||||
case ESurfaceFormat::X4R4G4B4: vk_format = VK_FORMAT_B4G4R4A4_UNORM_PACK16; format = ESurfaceFormat::A4R4G4B4; break;
|
||||
case ESurfaceFormat::A1R5G5B5: vk_format = VK_FORMAT_B5G5R5A1_UNORM_PACK16; break;
|
||||
case ESurfaceFormat::A4R4G4B4: vk_format = VK_FORMAT_B4G4R4A4_UNORM_PACK16; break;
|
||||
case ESurfaceFormat::R8G8B8: vk_format = VK_FORMAT_B8G8R8_UNORM; break;
|
||||
case ESurfaceFormat::B8G8R8: vk_format = VK_FORMAT_B8G8R8_UNORM; break;
|
||||
case ESurfaceFormat::X8R8G8B8: vk_format = VK_FORMAT_B8G8R8A8_UNORM; format = ESurfaceFormat::A8R8G8B8; break;
|
||||
case ESurfaceFormat::X8B8G8R8: vk_format = VK_FORMAT_B8G8R8A8_UNORM; format = ESurfaceFormat::X8R8G8B8; break;
|
||||
case ESurfaceFormat::A8R8G8B8: vk_format = VK_FORMAT_B8G8R8A8_UNORM; break;
|
||||
case ESurfaceFormat::A8B8G8R8: vk_format = VK_FORMAT_B8G8R8A8_UNORM; format = ESurfaceFormat::A8R8G8B8; break;
|
||||
case ESurfaceFormat::Invalid:
|
||||
default: JPH_ASSERT(false); break;
|
||||
}
|
||||
|
||||
// Blit the surface to another temporary surface if the format changed
|
||||
const Surface *surface = inSurface;
|
||||
Ref<Surface> tmp;
|
||||
if (format != inSurface->GetFormat())
|
||||
{
|
||||
tmp = new SoftwareSurface(mWidth, mHeight, format);
|
||||
BlitSurface(inSurface, tmp);
|
||||
surface = tmp;
|
||||
}
|
||||
|
||||
int bpp = surface->GetBytesPerPixel();
|
||||
VkDeviceSize image_size = VkDeviceSize(mWidth) * mHeight * bpp;
|
||||
VkDevice device = mRenderer->GetDevice();
|
||||
|
||||
BufferVK staging_buffer;
|
||||
mRenderer->CreateBuffer(image_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, staging_buffer);
|
||||
|
||||
// Copy data to upload texture
|
||||
surface->Lock(ESurfaceLockMode::Read);
|
||||
void *data;
|
||||
vkMapMemory(device, staging_buffer.mMemory, staging_buffer.mOffset, image_size, 0, &data);
|
||||
for (int y = 0; y < mHeight; ++y)
|
||||
memcpy(reinterpret_cast<uint8 *>(data) + y * mWidth * bpp, surface->GetData() + y * surface->GetStride(), mWidth * bpp);
|
||||
vkUnmapMemory(device, staging_buffer.mMemory);
|
||||
surface->UnLock();
|
||||
|
||||
// Create destination image
|
||||
mRenderer->CreateImage(mWidth, mHeight, vk_format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, mImage, mImageMemory);
|
||||
|
||||
VkCommandBuffer command_buffer = mRenderer->StartTempCommandBuffer();
|
||||
|
||||
// Make the image suitable for transferring to
|
||||
TransitionImageLayout(command_buffer, mImage, vk_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
// Copy the data to the destination image
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent = { uint32(mWidth), uint32(mHeight), 1 };
|
||||
vkCmdCopyBufferToImage(command_buffer, staging_buffer.mBuffer, mImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
// Make the image suitable for sampling
|
||||
TransitionImageLayout(command_buffer, mImage, vk_format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
mRenderer->EndTempCommandBuffer(command_buffer);
|
||||
|
||||
// Destroy temporary buffer
|
||||
mRenderer->FreeBuffer(staging_buffer);
|
||||
|
||||
CreateImageViewAndDescriptorSet(vk_format, VK_IMAGE_ASPECT_COLOR_BIT, mRenderer->GetTextureSamplerRepeat());
|
||||
}
|
||||
|
||||
TextureVK::TextureVK(RendererVK *inRenderer, int inWidth, int inHeight) :
|
||||
Texture(inWidth, inHeight),
|
||||
mRenderer(inRenderer)
|
||||
{
|
||||
VkFormat vk_format = mRenderer->FindDepthFormat();
|
||||
|
||||
// Create render target
|
||||
mRenderer->CreateImage(mWidth, mHeight, vk_format, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, mImage, mImageMemory);
|
||||
|
||||
CreateImageViewAndDescriptorSet(vk_format, VK_IMAGE_ASPECT_DEPTH_BIT, mRenderer->GetTextureSamplerShadow());
|
||||
}
|
||||
|
||||
TextureVK::~TextureVK()
|
||||
{
|
||||
if (mImage != VK_NULL_HANDLE)
|
||||
{
|
||||
VkDevice device = mRenderer->GetDevice();
|
||||
|
||||
vkDeviceWaitIdle(device);
|
||||
|
||||
vkDestroyImageView(device, mImageView, nullptr);
|
||||
|
||||
mRenderer->DestroyImage(mImage, mImageMemory);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureVK::Bind() const
|
||||
{
|
||||
if (mDescriptorSet != VK_NULL_HANDLE)
|
||||
vkCmdBindDescriptorSets(mRenderer->GetCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, mRenderer->GetPipelineLayout(), 1, 1, &mDescriptorSet, 0, nullptr);
|
||||
}
|
||||
|
||||
void TextureVK::CreateImageViewAndDescriptorSet(VkFormat inFormat, VkImageAspectFlags inAspectFlags, VkSampler inSampler)
|
||||
{
|
||||
VkDevice device = mRenderer->GetDevice();
|
||||
|
||||
// Create image view
|
||||
mImageView = mRenderer->CreateImageView(mImage, inFormat, inAspectFlags);
|
||||
|
||||
// Allocate descriptor set for binding the texture
|
||||
VkDescriptorSetLayout layout = mRenderer->GetDescriptorSetLayoutTexture();
|
||||
VkDescriptorSetAllocateInfo descriptor_set_alloc_info = {};
|
||||
descriptor_set_alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
descriptor_set_alloc_info.descriptorPool = mRenderer->GetDescriptorPool();
|
||||
descriptor_set_alloc_info.descriptorSetCount = 1;
|
||||
descriptor_set_alloc_info.pSetLayouts = &layout;
|
||||
FatalErrorIfFailed(vkAllocateDescriptorSets(device, &descriptor_set_alloc_info, &mDescriptorSet));
|
||||
|
||||
VkDescriptorImageInfo image_info = {};
|
||||
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
image_info.imageView = mImageView;
|
||||
image_info.sampler = inSampler;
|
||||
|
||||
VkWriteDescriptorSet descriptor_write = {};
|
||||
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
descriptor_write.dstSet = mDescriptorSet;
|
||||
descriptor_write.dstBinding = 0;
|
||||
descriptor_write.dstArrayElement = 0;
|
||||
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
descriptor_write.descriptorCount = 1;
|
||||
descriptor_write.pImageInfo = &image_info;
|
||||
vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, nullptr);
|
||||
}
|
||||
|
||||
void TextureVK::TransitionImageLayout(VkCommandBuffer inCommandBuffer, VkImage inImage, VkFormat inFormat, VkImageLayout inOldLayout, VkImageLayout inNewLayout)
|
||||
{
|
||||
VkImageMemoryBarrier barrier = {};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.oldLayout = inOldLayout;
|
||||
barrier.newLayout = inNewLayout;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = inImage;
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
|
||||
if (inOldLayout == VK_IMAGE_LAYOUT_UNDEFINED && inNewLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||||
{
|
||||
barrier.srcAccessMask = 0;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
vkCmdPipelineBarrier(inCommandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
}
|
||||
else if (inOldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && inNewLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||
{
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
vkCmdPipelineBarrier(inCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
}
|
||||
}
|
||||
35
lib/All/JoltPhysics/TestFramework/Renderer/VK/TextureVK.h
Normal file
35
lib/All/JoltPhysics/TestFramework/Renderer/VK/TextureVK.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Renderer/Texture.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
class RendererVK;
|
||||
|
||||
class TextureVK : public Texture
|
||||
{
|
||||
public:
|
||||
/// Constructor, called by Renderer::CreateTextureVK
|
||||
TextureVK(RendererVK *inRenderer, const Surface *inSurface); // Create a normal TextureVK
|
||||
TextureVK(RendererVK *inRenderer, int inWidth, int inHeight); // Create a render target (depth only)
|
||||
virtual ~TextureVK() override;
|
||||
|
||||
/// Bind texture to the pixel shader
|
||||
virtual void Bind() const override;
|
||||
|
||||
VkImageView GetImageView() const { return mImageView; }
|
||||
|
||||
private:
|
||||
void CreateImageViewAndDescriptorSet(VkFormat inFormat, VkImageAspectFlags inAspectFlags, VkSampler inSampler);
|
||||
void TransitionImageLayout(VkCommandBuffer inCommandBuffer, VkImage inImage, VkFormat inFormat, VkImageLayout inOldLayout, VkImageLayout inNewLayout);
|
||||
|
||||
RendererVK * mRenderer;
|
||||
VkImage mImage = VK_NULL_HANDLE;
|
||||
VkDeviceMemory mImageMemory = VK_NULL_HANDLE;
|
||||
VkImageView mImageView = VK_NULL_HANDLE;
|
||||
VkDescriptorSet mDescriptorSet = VK_NULL_HANDLE;
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Renderer/VertexShader.h>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
/// Vertex shader handle for Vulkan
|
||||
class VertexShaderVK : public VertexShader
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
VertexShaderVK(VkDevice inDevice, VkShaderModule inShaderModule) :
|
||||
mDevice(inDevice),
|
||||
mStageInfo()
|
||||
{
|
||||
mStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
mStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
mStageInfo.module = inShaderModule;
|
||||
mStageInfo.pName = "main";
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~VertexShaderVK() override
|
||||
{
|
||||
vkDestroyShaderModule(mDevice, mStageInfo.module, nullptr);
|
||||
}
|
||||
|
||||
VkDevice mDevice;
|
||||
VkPipelineShaderStageCreateInfo mStageInfo;
|
||||
};
|
||||
Reference in New Issue
Block a user