work
This commit is contained in:
parent
97008e92ca
commit
0b97e6eeec
|
@ -53,11 +53,19 @@ namespace orange
|
|||
T& back() { return data[size - 1]; }
|
||||
const T& back() const { return data[size - 1]; }
|
||||
|
||||
void Copy(void* dst)
|
||||
{
|
||||
memcpy(dst, data, sizeof(T) * size);
|
||||
}
|
||||
|
||||
T* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
using BufferView = Span<uint8_t>;
|
||||
struct BufferView : public Span<uint8_t>
|
||||
{
|
||||
using Span<uint8_t>::Span;
|
||||
};
|
||||
|
||||
struct StringView : public Span<const char>
|
||||
{
|
||||
|
@ -69,7 +77,7 @@ namespace orange
|
|||
|
||||
struct Buffer : public BufferView
|
||||
{
|
||||
using BufferView::Span;
|
||||
using BufferView::BufferView;
|
||||
|
||||
~Buffer() { delete[] data; }
|
||||
};
|
||||
|
|
|
@ -28,8 +28,8 @@ namespace orange
|
|||
new (Ptr<T>()) T(Forward(args)...);
|
||||
}
|
||||
|
||||
template <typename T> T* Ptr() { return reinterpret_cast<T*>(data.data); }
|
||||
template <typename T> const T* Ptr() const { return reinterpret_cast<T*>(data.data); }
|
||||
template <typename T> T* Ptr() { return reinterpret_cast<T*> (data.data); }
|
||||
template <typename T> const T* Ptr() const { return reinterpret_cast<const T*>(data.data); }
|
||||
|
||||
template <typename T> T& Get() { return *Ptr<T>(); }
|
||||
template <typename T> const T& Get() const { return *Ptr<T>(); }
|
||||
|
|
|
@ -166,6 +166,11 @@ namespace orange
|
|||
return FindIdx(x) != InvalidIdx;
|
||||
}
|
||||
|
||||
void Copy(void* dst)
|
||||
{
|
||||
memcpy(dst, Ptr(0), sizeof(T) * m_size);
|
||||
}
|
||||
|
||||
T& operator [] (size_t idx) { return *Ptr(idx); }
|
||||
const T& operator [] (size_t idx) const { return *Ptr(idx); }
|
||||
|
||||
|
@ -183,6 +188,8 @@ namespace orange
|
|||
|
||||
operator Span<T>() { return Span<T>(*this); }
|
||||
|
||||
operator BufferView() { return BufferView{ reinterpret_cast<uint8_t *>(Ptr(0)), sizeof(T) * m_size}; }
|
||||
|
||||
private:
|
||||
using Storage = AlignedStorage<sizeof(T), alignof(T)>;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
namespace orange
|
||||
{
|
||||
|
|
|
@ -8,16 +8,53 @@
|
|||
|
||||
namespace orange
|
||||
{
|
||||
class BufferPool
|
||||
struct BufferSlice
|
||||
{
|
||||
VkBuffer buffer;
|
||||
VkDeviceSize offset;
|
||||
VkDeviceSize size;
|
||||
};
|
||||
|
||||
struct GPUMemoryBuffer
|
||||
{
|
||||
VkDeviceMemory memory;
|
||||
VkBuffer buffer;
|
||||
VkDeviceSize size;
|
||||
void* ptr;
|
||||
};
|
||||
|
||||
class BufferPooler
|
||||
{
|
||||
public:
|
||||
BufferPooler(GPUMemoryBuffer buffer)
|
||||
: m_buffer{ buffer } {}
|
||||
|
||||
Result<BufferSlice> AllocSlice(VkDeviceSize size)
|
||||
{
|
||||
BufferSlice slice{ m_buffer.buffer, m_offset, size };
|
||||
|
||||
if (m_offset + size > m_buffer.size)
|
||||
return Result<BufferSlice>::Error();
|
||||
|
||||
m_offset += size;
|
||||
|
||||
return Result<BufferSlice>::Success(slice);
|
||||
}
|
||||
private:
|
||||
VkBuffer m_buffer;
|
||||
VkDeviceAddress m_va;
|
||||
GPUMemoryBuffer m_buffer = {};
|
||||
VkDeviceSize m_offset = 0u;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using VulkanResult = Result<T, VkResult, VK_SUCCESS, VK_ERROR_UNKNOWN, VK_ERROR_UNKNOWN>;
|
||||
|
||||
struct VkMemoryTypes
|
||||
{
|
||||
uint32_t cpuTypeIdx = -1;
|
||||
uint32_t gpuOnlyTypeIdx = -1;
|
||||
uint32_t gpuHostVisibleTypeIdx = -1;
|
||||
};
|
||||
|
||||
class RenderContext
|
||||
{
|
||||
public:
|
||||
|
@ -31,10 +68,11 @@ namespace orange
|
|||
VkQueue Queue() const { return m_queue; }
|
||||
VkCommandPool CommandPool() const { return m_commandPool; }
|
||||
|
||||
VulkanResult<VkFence> CreateFence(bool signalled);
|
||||
VulkanResult<VkSemaphore> CreateSemaphore();
|
||||
VulkanResult<VoidResult> BeginCommandBuffer(VkCommandBuffer buffer);
|
||||
VulkanResult<VoidResult> EndCommandBuffer(VkCommandBuffer buffer);
|
||||
VulkanResult<VkFence> CreateFence(bool signalled);
|
||||
VulkanResult<VkSemaphore> CreateSemaphore();
|
||||
VulkanResult<VoidResult> BeginCommandBuffer(VkCommandBuffer buffer);
|
||||
VulkanResult<VoidResult> EndCommandBuffer(VkCommandBuffer buffer);
|
||||
VulkanResult<GPUMemoryBuffer> CreateBuffer(VkDeviceSize size);
|
||||
|
||||
VulkanResult<VkShaderModule> CreateShader(Span<const uint32_t> code);
|
||||
protected:
|
||||
|
@ -42,12 +80,52 @@ namespace orange
|
|||
RenderContext(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device,
|
||||
VkQueue queue, VkCommandPool commandPool)
|
||||
: m_instance{ instance }, m_physicalDevice{ physicalDevice }, m_device{ device }
|
||||
, m_queue{ queue }, m_commandPool{ commandPool } {}
|
||||
, m_queue{ queue }, m_commandPool{ commandPool }
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties memoryProps;
|
||||
vkGetPhysicalDeviceMemoryProperties(m_physicalDevice, &memoryProps);
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t* ptr;
|
||||
VkMemoryPropertyFlags flags;
|
||||
} memoryTypeMapping[] =
|
||||
{
|
||||
{ &m_memoryTypes.gpuHostVisibleTypeIdx,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT },
|
||||
|
||||
{ &m_memoryTypes.gpuOnlyTypeIdx,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT },
|
||||
|
||||
{ &m_memoryTypes.cpuTypeIdx,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT },
|
||||
};
|
||||
|
||||
for (auto& mapping : memoryTypeMapping)
|
||||
{
|
||||
for (uint32_t i = 0; i < memoryProps.memoryTypeCount; i++)
|
||||
{
|
||||
if (memoryProps.memoryTypes[i].propertyFlags & mapping.flags)
|
||||
{
|
||||
*mapping.ptr = i;
|
||||
|
||||
if (memoryProps.memoryTypes[i].propertyFlags == mapping.flags)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private:
|
||||
VkInstance m_instance = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice m_physicalDevice = VK_NULL_HANDLE;
|
||||
VkDevice m_device = VK_NULL_HANDLE;
|
||||
VkQueue m_queue = VK_NULL_HANDLE;
|
||||
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
||||
|
||||
VkMemoryTypes m_memoryTypes{};
|
||||
};
|
||||
}
|
|
@ -11,8 +11,9 @@
|
|||
#include <Orange/Render/Window.h>
|
||||
#include <Orange/Render/RenderContext.h>
|
||||
#include <Orange/Render/Swapchain.h>
|
||||
#include <Orange/Render/VulkanHelpers.h>
|
||||
|
||||
#include <vs_Triangle.h>
|
||||
#include <vs_Mesh.h>
|
||||
#include <fs_DebugVertColor.h>
|
||||
|
||||
using namespace orange;
|
||||
|
@ -35,19 +36,30 @@ enum class MeshVertexType
|
|||
Skinned,
|
||||
};
|
||||
|
||||
#ifndef offsetof2
|
||||
#define offsetof2(type, member) size_t(uintptr_t(&((type*)0)->member))
|
||||
#endif
|
||||
|
||||
struct StaticVertex
|
||||
{
|
||||
vec3 pos;
|
||||
vec2 uv;
|
||||
vec3 normal;
|
||||
vec3 tangent;
|
||||
//vec3 tangent;
|
||||
|
||||
static constexpr VkVertexInputAttributeDescription Attributes[] =
|
||||
{
|
||||
{ .location = 0, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = uint32_t(offsetof2(StaticVertex, pos)) },
|
||||
{ .location = 1, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, .offset = uint32_t(offsetof2(StaticVertex, uv)) },
|
||||
{ .location = 2, .binding = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = uint32_t(offsetof2(StaticVertex, normal)) },
|
||||
};
|
||||
|
||||
bool operator == (const StaticVertex& other) const
|
||||
{
|
||||
return pos == other.pos &&
|
||||
uv == other.uv &&
|
||||
normal == other.normal &&
|
||||
tangent == other.tangent;
|
||||
normal == other.normal;// &&
|
||||
//tangent == other.tangent;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -60,7 +72,7 @@ struct SkinnedVertex : public StaticVertex
|
|||
return pos == other.pos &&
|
||||
uv == other.uv &&
|
||||
normal == other.normal &&
|
||||
tangent == other.tangent &&
|
||||
//tangent == other.tangent &&
|
||||
boneIndices == other.boneIndices &&
|
||||
boneWeights == other.boneWeights;
|
||||
}
|
||||
|
@ -74,7 +86,7 @@ struct MeshVertexData
|
|||
MeshVertexData(MeshVertexType type)
|
||||
: vertexType(type)
|
||||
{
|
||||
switch(type)
|
||||
switch(vertexType)
|
||||
{
|
||||
case MeshVertexType::Static:
|
||||
vertices.Construct<Vector<StaticVertex>>();
|
||||
|
@ -97,6 +109,27 @@ struct MeshVertexData
|
|||
return vertices.Get<Vector<SkinnedVertex>>();
|
||||
}
|
||||
|
||||
BufferView View()
|
||||
{
|
||||
switch(vertexType)
|
||||
{
|
||||
case MeshVertexType::Static:
|
||||
return GetStaticVertices();
|
||||
break;
|
||||
case MeshVertexType::Skinned:
|
||||
return GetSkinnedVertices();
|
||||
break;
|
||||
default:
|
||||
return BufferView{ nullptr, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t VertexCount() const
|
||||
{
|
||||
// Type doesn't matter here, just want to grab m_size.
|
||||
return uint32_t(vertices.Get<Vector<uint8_t>>().Size());
|
||||
}
|
||||
|
||||
MeshVertexType vertexType;
|
||||
Variant<Vector<StaticVertex>, Vector<SkinnedVertex>> vertices;
|
||||
};
|
||||
|
@ -134,16 +167,14 @@ Result<MeshData> ParseOBJ(StringView buffer)
|
|||
stream::ConsumeSpace(obj, end);
|
||||
if (auto r_float = stream::Parse<float>(obj, end))
|
||||
vtx[i] = *r_float;
|
||||
else
|
||||
return Result<MeshData>::Error();
|
||||
}
|
||||
|
||||
if (element == "v")
|
||||
positions.EmplaceBack(vtx[0], vtx[1], vtx[2]);
|
||||
else if (element == "vt")
|
||||
normals.EmplaceBack(vtx[0], vtx[1], vtx[2]);
|
||||
else if (element == "vn")
|
||||
uvs.EmplaceBack(vtx[0], vtx[1]);
|
||||
else if (element == "vn")
|
||||
normals.EmplaceBack(vtx[0], vtx[1], vtx[2]);
|
||||
}
|
||||
else if (element == "g" || element == "o")
|
||||
{
|
||||
|
@ -230,17 +261,135 @@ int main(int argc, char** argv)
|
|||
if (!r_swapchain)
|
||||
return 1;
|
||||
|
||||
auto r_objData = fs::OpenFileIntoTextBuffer("/home/joshua/chair.obj");
|
||||
//auto r_objData = fs::OpenFileIntoTextBuffer("/home/joshua/chair.obj");
|
||||
auto r_objData = fs::OpenFileIntoTextBuffer("/home/joshua/cube.obj");
|
||||
if (!r_objData)
|
||||
return 1;
|
||||
|
||||
auto r_mesh = ParseOBJ(*r_objData);
|
||||
|
||||
auto r_vs = r_renderContext->CreateShader(vs_Triangle);
|
||||
auto r_vs = r_renderContext->CreateShader(vs_Mesh);
|
||||
if (!r_vs) return 1;
|
||||
auto r_fs = r_renderContext->CreateShader(fs_DebugVertColor);
|
||||
if (!r_fs) return 1;
|
||||
|
||||
//
|
||||
|
||||
VkSamplerCreateInfo samplerInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.magFilter = VK_FILTER_LINEAR,
|
||||
.minFilter = VK_FILTER_LINEAR,
|
||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.mipLodBias = 0.0f,
|
||||
.anisotropyEnable = VK_TRUE,
|
||||
.maxAnisotropy = 16.0f,
|
||||
.minLod = -FLT_MAX,
|
||||
.maxLod = FLT_MAX,
|
||||
};
|
||||
VkSampler sampler = VK_NULL_HANDLE;
|
||||
vkCreateSampler(r_renderContext->Device(), &samplerInfo, nullptr, &sampler);
|
||||
|
||||
constexpr uint32_t MaxBindlessResources = 32768;
|
||||
VkDescriptorPoolSize bindlessPoolSizes[] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MaxBindlessResources }
|
||||
};
|
||||
|
||||
VkDescriptorPoolCreateInfo poolInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
|
||||
.maxSets = MaxBindlessResources * Size(bindlessPoolSizes),
|
||||
.poolSizeCount = uint32_t(Size(bindlessPoolSizes)),
|
||||
.pPoolSizes = bindlessPoolSizes,
|
||||
};
|
||||
|
||||
VkDescriptorPool descriptorPool = VK_NULL_HANDLE;
|
||||
vkCreateDescriptorPool(r_renderContext->Device(), &poolInfo, nullptr, &descriptorPool);
|
||||
|
||||
VkDescriptorSetLayoutBinding layoutBindings[] =
|
||||
{
|
||||
{
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = MaxBindlessResources,
|
||||
.stageFlags = VK_SHADER_STAGE_ALL,
|
||||
},
|
||||
{
|
||||
.binding = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
|
||||
.descriptorCount = MaxBindlessResources,
|
||||
.stageFlags = VK_SHADER_STAGE_ALL,
|
||||
},
|
||||
{
|
||||
.binding = 2,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.pImmutableSamplers = &sampler,
|
||||
},
|
||||
{
|
||||
.binding = 3,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.descriptorCount = MaxBindlessResources,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
},
|
||||
};
|
||||
|
||||
constexpr VkDescriptorBindingFlags bindingFlags[] =
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT,
|
||||
};
|
||||
|
||||
Assert(Size(bindingFlags) == Size(layoutBindings));
|
||||
|
||||
VkDescriptorSetLayoutBindingFlagsCreateInfo layoutBindingFlagsInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT,
|
||||
.bindingCount = Size(bindingFlags),
|
||||
.pBindingFlags = bindingFlags,
|
||||
};
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo layoutInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.pNext = &layoutBindingFlagsInfo,
|
||||
.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT,
|
||||
.bindingCount = Size(layoutBindings),
|
||||
.pBindings = layoutBindings,
|
||||
};
|
||||
|
||||
VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE;
|
||||
vkCreateDescriptorSetLayout(r_renderContext->Device(), &layoutInfo, nullptr, &descriptorSetLayout);
|
||||
|
||||
VkDescriptorSetVariableDescriptorCountAllocateInfoEXT descriptorCountAllocInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT,
|
||||
.descriptorSetCount = 1,
|
||||
.pDescriptorCounts = &MaxBindlessResources,
|
||||
};
|
||||
|
||||
VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.pNext = &descriptorCountAllocInfo,
|
||||
.descriptorPool = descriptorPool,
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &descriptorSetLayout,
|
||||
};
|
||||
|
||||
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
||||
vkAllocateDescriptorSets(r_renderContext->Device(), &descriptorSetAllocInfo, &descriptorSet);
|
||||
|
||||
//
|
||||
|
||||
VkPipelineShaderStageCreateInfo stages[] =
|
||||
{
|
||||
{
|
||||
|
@ -270,13 +419,20 @@ int main(int argc, char** argv)
|
|||
.pDynamicStates = dynamicStates.Data(),
|
||||
};
|
||||
|
||||
VkVertexInputBindingDescription inputBindingDescription =
|
||||
{
|
||||
.binding = 0,
|
||||
.stride = sizeof(StaticVertex),
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
|
||||
};
|
||||
|
||||
VkPipelineVertexInputStateCreateInfo vertexInputInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||
.vertexBindingDescriptionCount = 0u,
|
||||
.pVertexBindingDescriptions = nullptr,
|
||||
.vertexAttributeDescriptionCount = 0u,
|
||||
.pVertexAttributeDescriptions = nullptr,
|
||||
.vertexBindingDescriptionCount = 1u,
|
||||
.pVertexBindingDescriptions = &inputBindingDescription,
|
||||
.vertexAttributeDescriptionCount = Size(StaticVertex::Attributes),
|
||||
.pVertexAttributeDescriptions = StaticVertex::Attributes,
|
||||
};
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo =
|
||||
|
@ -298,6 +454,7 @@ int main(int argc, char** argv)
|
|||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||
.cullMode = VK_CULL_MODE_NONE, //VK_CULL_MODE_BACK_BIT,
|
||||
.frontFace = VK_FRONT_FACE_CLOCKWISE,
|
||||
.lineWidth = 1.0f,
|
||||
};
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo multisampleInfo =
|
||||
|
@ -321,12 +478,14 @@ int main(int argc, char** argv)
|
|||
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = 1,
|
||||
.pSetLayouts = &descriptorSetLayout
|
||||
};
|
||||
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
|
||||
vkCreatePipelineLayout(r_renderContext->Device(), &pipelineLayoutInfo, nullptr, &pipelineLayout);
|
||||
|
||||
VkFormat format = r_swapchain->Format();
|
||||
VkFormat format = FormatToSrgbFormat(r_swapchain->Format());
|
||||
VkPipelineRenderingCreateInfo renderingInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
||||
|
@ -359,6 +518,57 @@ int main(int argc, char** argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
auto r_buffer = r_renderContext->CreateBuffer(256 * 1024 * 1024);
|
||||
if (!r_buffer)
|
||||
return 1;
|
||||
|
||||
VkBufferViewCreateInfo bufferViewInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
|
||||
.buffer = r_buffer->buffer,
|
||||
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
.offset = 0,
|
||||
.range = r_buffer->size,
|
||||
};
|
||||
VkBufferView bufferView = VK_NULL_HANDLE;
|
||||
vkCreateBufferView(r_renderContext->Device(), &bufferViewInfo, nullptr, &bufferView);
|
||||
|
||||
VkDescriptorBufferInfo bufferInfo =
|
||||
{
|
||||
.buffer = r_buffer->buffer,
|
||||
.offset = 0,
|
||||
.range = r_buffer->size,
|
||||
};
|
||||
|
||||
VkWriteDescriptorSet writeDescriptorSet[] =
|
||||
{
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptorSet,
|
||||
.dstBinding = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.pBufferInfo = &bufferInfo,
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = descriptorSet,
|
||||
.dstBinding = 1,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
|
||||
.pTexelBufferView = &bufferView,
|
||||
},
|
||||
};
|
||||
vkUpdateDescriptorSets(r_renderContext->Device(), Size(writeDescriptorSet), writeDescriptorSet, 0, nullptr);
|
||||
|
||||
auto pooler = BufferPooler{ *r_buffer };
|
||||
auto meshData = r_mesh->vertexData.View();
|
||||
auto vertexSlice = *pooler.AllocSlice(meshData.size);
|
||||
auto indexSlice = *pooler.AllocSlice(r_mesh->indices.Size() * sizeof(uint16_t));
|
||||
|
||||
meshData.Copy ((uint8_t*)(r_buffer->ptr) + vertexSlice.offset);
|
||||
r_mesh->indices.Copy((uint8_t*)(r_buffer->ptr) + indexSlice.offset);
|
||||
|
||||
while (r_window->Update())
|
||||
{
|
||||
VkCommandBuffer cmdBuf = r_swapchain->CommandBuffer();
|
||||
|
@ -384,6 +594,29 @@ int main(int argc, char** argv)
|
|||
vkCmdSetScissor(cmdBuf, 0, 1, &scissor);
|
||||
|
||||
vkCmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
vkCmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
|
||||
|
||||
vkCmdBindVertexBuffers2(cmdBuf, 0, 1, &vertexSlice.buffer, &vertexSlice.offset, &vertexSlice.size, nullptr);
|
||||
vkCmdBindIndexBuffer(cmdBuf, r_buffer->buffer, indexSlice.offset, VK_INDEX_TYPE_UINT16);
|
||||
|
||||
const VkImageMemoryBarrier undefinedToColorBarrier =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.image = r_swapchain->Image(),
|
||||
.subresourceRange = FirstMipSubresourceRange,
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
cmdBuf,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &undefinedToColorBarrier);
|
||||
|
||||
const VkRenderingAttachmentInfoKHR attachmentInfo =
|
||||
{
|
||||
|
@ -404,8 +637,27 @@ int main(int argc, char** argv)
|
|||
.pColorAttachments = &attachmentInfo,
|
||||
};
|
||||
vkCmdBeginRendering(cmdBuf, &renderInfo);
|
||||
vkCmdDraw(cmdBuf, 3, 1, 0, 0);
|
||||
vkCmdDrawIndexed(cmdBuf, r_mesh->vertexData.VertexCount(), 1, 0, 0, 0);
|
||||
vkCmdEndRendering(cmdBuf);
|
||||
|
||||
const VkImageMemoryBarrier colorToPresentBarrier =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
.image = r_swapchain->Image(),
|
||||
.subresourceRange = FirstMipSubresourceRange,
|
||||
};
|
||||
|
||||
vkCmdPipelineBarrier(
|
||||
cmdBuf,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &colorToPresentBarrier);
|
||||
}
|
||||
r_renderContext->EndCommandBuffer(cmdBuf);
|
||||
r_swapchain->Present();
|
||||
|
|
|
@ -115,13 +115,50 @@ namespace orange
|
|||
const char* deviceExtensions[] =
|
||||
{
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||
VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceFeatures features{};
|
||||
VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeatures =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES,
|
||||
.dynamicRendering = VK_TRUE,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexingFeatures =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
|
||||
.pNext = &dynamicRenderingFeatures,
|
||||
.shaderInputAttachmentArrayDynamicIndexing = VK_FALSE,
|
||||
.shaderUniformTexelBufferArrayDynamicIndexing = VK_TRUE,
|
||||
.shaderStorageTexelBufferArrayDynamicIndexing = VK_TRUE,
|
||||
.shaderUniformBufferArrayNonUniformIndexing = VK_TRUE,
|
||||
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
|
||||
.shaderStorageBufferArrayNonUniformIndexing = VK_TRUE,
|
||||
.shaderStorageImageArrayNonUniformIndexing = VK_TRUE,
|
||||
.shaderInputAttachmentArrayNonUniformIndexing = VK_FALSE,
|
||||
.shaderUniformTexelBufferArrayNonUniformIndexing = VK_TRUE,
|
||||
.shaderStorageTexelBufferArrayNonUniformIndexing = VK_TRUE,
|
||||
.descriptorBindingUniformBufferUpdateAfterBind = VK_TRUE,
|
||||
.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE,
|
||||
.descriptorBindingStorageImageUpdateAfterBind = VK_TRUE,
|
||||
.descriptorBindingStorageBufferUpdateAfterBind = VK_TRUE,
|
||||
.descriptorBindingUniformTexelBufferUpdateAfterBind = VK_TRUE,
|
||||
.descriptorBindingStorageTexelBufferUpdateAfterBind = VK_TRUE,
|
||||
.descriptorBindingUpdateUnusedWhilePending = VK_TRUE,
|
||||
.descriptorBindingPartiallyBound = VK_TRUE,
|
||||
.descriptorBindingVariableDescriptorCount = VK_TRUE,
|
||||
.runtimeDescriptorArray = VK_TRUE,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceFeatures features
|
||||
{
|
||||
.samplerAnisotropy = VK_TRUE,
|
||||
};
|
||||
|
||||
VkDeviceCreateInfo deviceInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = &descriptorIndexingFeatures,
|
||||
.queueCreateInfoCount = 1,
|
||||
.pQueueCreateInfos = &queueInfo,
|
||||
.enabledExtensionCount = Size(deviceExtensions),
|
||||
|
|
|
@ -72,4 +72,44 @@ namespace orange
|
|||
|
||||
return VulkanResult<VkShaderModule>::Success(module);
|
||||
}
|
||||
|
||||
VulkanResult<GPUMemoryBuffer> RenderContext::CreateBuffer(VkDeviceSize size)
|
||||
{
|
||||
VkMemoryAllocateInfo memoryInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.allocationSize = size,
|
||||
.memoryTypeIndex = m_memoryTypes.gpuHostVisibleTypeIdx,
|
||||
};
|
||||
|
||||
VkDeviceMemory memory;
|
||||
VkResult res = VK_SUCCESS;
|
||||
if ((res = vkAllocateMemory(m_device, &memoryInfo, nullptr, &memory)) != VK_SUCCESS)
|
||||
return VulkanResult<GPUMemoryBuffer>::Error(res);
|
||||
|
||||
void* data = nullptr;
|
||||
if ((res = vkMapMemory(m_device, memory, 0, size, 0, &data)) != VK_SUCCESS)
|
||||
return VulkanResult<GPUMemoryBuffer>::Error(res);
|
||||
|
||||
VkBufferCreateInfo bufferInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||
.size = size,
|
||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
|
||||
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||
VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
|
||||
};
|
||||
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
if ((res = vkCreateBuffer(m_device, &bufferInfo, nullptr, &buffer)) != VK_SUCCESS)
|
||||
return VulkanResult<GPUMemoryBuffer>::Error(res);
|
||||
|
||||
if ((res = vkBindBufferMemory(m_device, buffer, memory, 0)) != VK_SUCCESS)
|
||||
return VulkanResult<GPUMemoryBuffer>::Error(res);
|
||||
|
||||
return VulkanResult<GPUMemoryBuffer>::Success(memory, buffer, size, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 inPos;
|
||||
layout(location = 1) in vec2 inUV;
|
||||
layout(location = 2) in vec3 inNormal;
|
||||
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
vec3 colors[3] = vec3[]
|
||||
(
|
||||
vec3(1.0, 0.0, 0.0),
|
||||
vec3(0.0, 1.0, 0.0),
|
||||
vec3(0.0, 0.0, 1.0)
|
||||
);
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(inPos, 1.0);
|
||||
outColor = vec4(colors[gl_VertexIndex], 1.0);
|
||||
}
|
|
@ -77,9 +77,24 @@ namespace orange
|
|||
|
||||
const VkExtent2D extent = ChooseSwapExtent(capabilities);
|
||||
|
||||
VkFormat viewFormats[2] =
|
||||
{
|
||||
r_format->format,
|
||||
FormatToSrgbFormat(r_format->format),
|
||||
};
|
||||
|
||||
VkImageFormatListCreateInfo formatListInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
|
||||
.viewFormatCount = Size(viewFormats),
|
||||
.pViewFormats = viewFormats,
|
||||
};
|
||||
|
||||
VkSwapchainCreateInfoKHR swapchainInfo =
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||
.pNext = &formatListInfo,
|
||||
.flags = VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR,
|
||||
.surface = surface,
|
||||
.minImageCount = ChooseImageCount(capabilities),
|
||||
.imageFormat = r_format->format,
|
||||
|
@ -171,6 +186,8 @@ namespace orange
|
|||
|
||||
void Swapchain::Present()
|
||||
{
|
||||
vkResetFences(m_ctx.Device(), 1, &m_inFlightFences[m_currentFrame]);
|
||||
|
||||
const VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo submitInfo =
|
||||
{
|
||||
|
@ -209,10 +226,9 @@ namespace orange
|
|||
|
||||
m_currentFrame = (m_currentFrame + 1) % DefaultFramesInFlight;
|
||||
|
||||
vkResetCommandBuffer(m_commandBuffers[m_currentFrame], 0u);
|
||||
|
||||
vkWaitForFences(m_ctx.Device(), 1, &m_inFlightFences[m_currentFrame], VK_TRUE, UINT64_MAX);
|
||||
vkResetFences(m_ctx.Device(), 1, &m_inFlightFences[m_currentFrame]);
|
||||
vkAcquireNextImageKHR(m_ctx.Device(), m_swapchain, ~0u, m_imageAvailableSemaphores[m_currentFrame], VK_NULL_HANDLE, &m_currentImage);
|
||||
|
||||
vkResetCommandBuffer(m_commandBuffers[m_currentFrame], 0u);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
orange_shaders = glsl_generator.process([
|
||||
'Render/Shaders/fs_DebugVertColor.frag',
|
||||
'Render/Shaders/vs_Triangle.vert',
|
||||
'Render/Shaders/vs_Mesh.vert',
|
||||
])
|
||||
|
||||
orange_src = files([
|
||||
|
|
Loading…
Reference in New Issue