1
0
Fork 0

Vulkan first texture

tmp
May B. 2020-10-01 19:54:02 +02:00
parent 3ea83d40ac
commit a3d9a157f3
15 changed files with 422 additions and 72 deletions

BIN
resource/content/shaders/Tris.fs.spv (Stored with Git LFS)

Binary file not shown.

BIN
resource/content/shaders/Tris.vs.spv (Stored with Git LFS)

Binary file not shown.

View File

@ -1,10 +1,13 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(binding = 1) uniform sampler2D texSampler;
layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor, 1.0);
outColor = texture(texSampler, fragTexCoord);
}

View File

@ -9,10 +9,13 @@ layout(binding = 0) uniform UniformBufferObject {
layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord;
layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;
void main() {
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0);
fragColor = inColor;
fragTexCoord = inTexCoord;
}

View File

@ -72,7 +72,7 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons
ImGui::SameLine();
changeRenderer |= ImGui::Checkbox("Stochastic", &options.renderer.voxel.stochastic);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Hide textures tilling\nMay cause visible inconsistances on chunk borders");
ImGui::SetTooltip("Hide textures tiling\nMay cause visible inconsistances on chunk borders");
changeRenderer |= ImGui::Checkbox("Geometry", &options.renderer.voxel.geometry);
ImGui::SameLine();

View File

@ -22,9 +22,9 @@ Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info): physicalD
}
updateProperties();
{
{ // Transfer
if (!info.queueIndices.transferFamily.has_value()) {
LOG_W("No transfer queue family. Using graphics one");
LOG_W("No transfer queue family. Fallback to graphics one");
}
const auto family = info.queueIndices.transferFamily.value_or(info.queueIndices.graphicsFamily.value());
@ -37,8 +37,7 @@ Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info): physicalD
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &transferPool) != VK_SUCCESS) {
FATAL("Failed to create transfer pool!");
}
}
{
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
@ -48,12 +47,33 @@ Allocator::Allocator(VkDevice device, const PhysicalDeviceInfo &info): physicalD
vkAllocateCommandBuffers(device, &allocInfo, &transferBuffer);
tracyCtx = TracyVkContext(info.device, device, transferQueue, transferBuffer);
}
{ // Graphics
vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue);
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = info.queueIndices.graphicsFamily.value();
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
if (vkCreateCommandPool(device, &poolInfo, ALLOC, &graphicsPool) != VK_SUCCESS) {
FATAL("Failed to create graphics pool!");
}
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = graphicsPool;
allocInfo.commandBufferCount = 1;
vkAllocateCommandBuffers(device, &allocInfo, &graphicsBuffer);
}
}
Allocator::~Allocator() {
TracyVkDestroy(tracyCtx);
vkFreeCommandBuffers(device, transferPool, 1, &transferBuffer);
vkFreeCommandBuffers(device, graphicsPool, 1, &graphicsBuffer);
vkDestroyCommandPool(device, transferPool, ALLOC);
vkDestroyCommandPool(device, graphicsPool, ALLOC);
//NOTE: all allocations are delete by ~vector
}
@ -189,6 +209,39 @@ Allocator::memory_ptr Allocator::createBuffers(const std::vector<buffer_requirem
return memory;
}
Allocator::memory_ptr Allocator::createImage(const VkImageCreateInfo& info, VkMemoryPropertyFlags properties, image_info& out,
const void *data, VkDeviceSize data_size, VkDeviceSize data_offset, VkImageLayout finalLayout) {
if (vkCreateImage(device, &info, ALLOC, &out.image) != VK_SUCCESS) {
LOG_E("Failed to create image");
return GetNull();
}
out.offset = 0;
VkMemoryRequirements memRequirements;
vkGetImageMemoryRequirements(device, out.image, &memRequirements);
auto memory = allocate(memRequirements, properties, true);
if (!memory || vkBindImageMemory(device, out.image, memory->ref, memory->offset) != VK_SUCCESS) {
LOG_E("Failed to allocate image memory");
return GetNull();
}
if (data_size != 0 && data != nullptr) {
Allocator::buffer_info stagingBuffer;
if(auto stagingMemory = createBuffer({data_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT}, HOST_EASILY_WRITABLE, stagingBuffer)) {
stagingMemory->write(data, data_size, data_offset);
transitionImageLayout(out.image, info.format, info.initialLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
copyBufferToImage(stagingBuffer, out, info.extent.width, info.extent.height);
transitionImageLayout(out.image, info.format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, finalLayout);
vkDestroyBuffer(device, stagingBuffer.buffer, ALLOC); //TODO: move to buffer destructor
} else {
FATAL("Cannot allocate staging memory");
return GetNull();
}
}
return memory;
}
void Allocator::updateProperties() {
if (hasBudget()) {
@ -203,12 +256,12 @@ void Allocator::updateProperties() {
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &properties);
}
}
Allocator::memory_ptr Allocator::allocate(VkMemoryRequirements requirements, VkMemoryPropertyFlags properties) {
Allocator::memory_ptr Allocator::allocate(VkMemoryRequirements requirements, VkMemoryPropertyFlags properties, bool optimalTiling) {
// Search in existing allocations
for (auto& alloc: allocations) {
if ((requirements.memoryTypeBits & (1 << alloc->memoryType)) &&
(getProperties().memoryTypes[alloc->memoryType].propertyFlags & properties) == properties &&
alloc->size > requirements.size
alloc->size > requirements.size && alloc->optimalTiling == optimalTiling
) {
VkDeviceSize start = 0;
auto aligned = [&](VkDeviceSize offset) {
@ -261,20 +314,36 @@ Allocator::memory_ptr Allocator::allocate(VkMemoryRequirements requirements, VkM
vkMapMemory(device, memory, 0, VK_WHOLE_SIZE, 0, &ptr);
}
auto allocation = allocations.emplace_back(new Allocation(device, memory, allocInfo.allocationSize, allocInfo.memoryTypeIndex, ptr)).get();
auto allocation = allocations.emplace_back(new Allocation(device, memory, allocInfo.allocationSize, allocInfo.memoryTypeIndex, optimalTiling, ptr)).get();
allocation->areas.push_back({requirements.size, 0});
return memory_ptr(new memory_area{memory, requirements.size, 0, ptr}, allocation->deleter);
}
void Allocator::copyBuffer(buffer_info src, buffer_info dst, VkDeviceSize size) {
//FIXME: assert no out of range
void beginCmd(VkCommandBuffer buffer) {
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(transferBuffer, &beginInfo);
vkBeginCommandBuffer(buffer, &beginInfo);
}
void submitCmd(VkCommandBuffer buffer, VkQueue queue) {
vkEndCommandBuffer(buffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &buffer;
vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
//TODO: parallelize
vkQueueWaitIdle(queue); //MAYBE: use fences
vkResetCommandBuffer(buffer, 0);
}
void Allocator::copyBuffer(buffer_info src, buffer_info dst, VkDeviceSize size) {
//FIXME: assert no out of range
beginCmd(transferBuffer);
VkBufferCopy copyRegion{};
copyRegion.srcOffset = 0;
@ -282,17 +351,70 @@ void Allocator::copyBuffer(buffer_info src, buffer_info dst, VkDeviceSize size)
copyRegion.size = size;
vkCmdCopyBuffer(transferBuffer, src.buffer, dst.buffer, 1, &copyRegion);
vkEndCommandBuffer(transferBuffer);
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &transferBuffer;
vkQueueSubmit(transferQueue, 1, &submitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(transferQueue); //MAYBE: use fences
vkResetCommandBuffer(transferBuffer, 0);
submitCmd(transferBuffer, transferQueue);
}
void Allocator::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) {
beginCmd(graphicsBuffer);
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = oldLayout;
barrier.newLayout = newLayout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
VkPipelineStageFlags sourceStage;
VkPipelineStageFlags destinationStage;
if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} else {
FATAL("Unsupported layout transition!");
}
vkCmdPipelineBarrier(graphicsBuffer, sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
submitCmd(graphicsBuffer, graphicsQueue);
}
void Allocator::copyBufferToImage(buffer_info src, image_info dest, uint32_t width, uint32_t height) {
beginCmd(transferBuffer);
VkBufferImageCopy region{};
region.bufferOffset = src.offset;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = {0, 0, 0};
region.imageExtent = {width, height, 1};
vkCmdCopyBufferToImage(transferBuffer, src.buffer, dest.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
submitCmd(transferBuffer, transferQueue);
}
std::optional<uint32_t> Allocator::findMemory(uint32_t typeFilter, VkMemoryPropertyFlags requirement, VkDeviceSize size) {
updateProperties();
@ -350,8 +472,8 @@ void Allocator::MemoryDeleter::operator()(memory_area* area) {
LOG_E("Allocation area not found");
delete area;
}
Allocator::Allocation::Allocation(VkDevice device, VkDeviceMemory memory, VkDeviceSize size, uint32_t memoryType, void *ptr):
device(device), memory(memory), size(size), memoryType(memoryType), ptr(ptr), deleter(this) { }
Allocator::Allocation::Allocation(VkDevice device, VkDeviceMemory memory, VkDeviceSize size, uint32_t memoryType, bool optimalTiling, void *ptr):
device(device), memory(memory), size(size), memoryType(memoryType), optimalTiling(optimalTiling), ptr(ptr), deleter(this) { }
Allocator::Allocation::~Allocation() {
if(!areas.empty())
LOG_E("Freeing " << areas.size() << " floating buffers");

View File

@ -38,7 +38,7 @@ public:
using memory_ptr = std::unique_ptr<memory_area, MemoryDeleter>;
memory_ptr allocate(VkMemoryRequirements, VkMemoryPropertyFlags);
memory_ptr allocate(VkMemoryRequirements, VkMemoryPropertyFlags, bool optimalTiling = false);
bool deallocate(const memory_area&);
struct buffer_info {
@ -55,7 +55,17 @@ public:
memory_ptr createBuffer(const buffer_requirement&, VkMemoryPropertyFlags, buffer_info&);
memory_ptr createBuffers(const std::vector<buffer_requirement> &, VkMemoryPropertyFlags, std::vector<buffer_info> &);
struct image_info {
VkImage image = nullptr;
VkDeviceSize offset = 0;
};
memory_ptr createImage(const VkImageCreateInfo&, VkMemoryPropertyFlags, image_info&,
const void *data = nullptr, VkDeviceSize data_size = 0, VkDeviceSize data_offset = 0,
VkImageLayout finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
void copyBuffer(buffer_info srcBuffer, buffer_info dstBuffer, VkDeviceSize size);
void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout);
void copyBufferToImage(buffer_info buffer, image_info image, uint32_t width, uint32_t height);
void setTracyZone(const char* name);
@ -68,13 +78,14 @@ private:
void updateProperties();
struct Allocation {
Allocation(VkDevice, VkDeviceMemory, VkDeviceSize, uint32_t, void *ptr);
Allocation(VkDevice, VkDeviceMemory, VkDeviceSize, uint32_t, bool optimalTiling, void *ptr);
~Allocation();
const VkDevice device;
const VkDeviceMemory memory;
const VkDeviceSize size;
const uint32_t memoryType;
const bool optimalTiling;
void *const ptr = nullptr;
const MemoryDeleter deleter;
@ -92,6 +103,9 @@ private:
VkCommandPool transferPool;
VkCommandBuffer transferBuffer; // MAYBE: parallel upload
TracyVkCtx tracyCtx;
VkQueue graphicsQueue;
VkCommandPool graphicsPool;
VkCommandBuffer graphicsBuffer;
std::vector<std::unique_ptr<Allocation>> allocations;
};

View File

@ -4,12 +4,18 @@
#include "Pipeline.hpp"
#include "../Renderer.hpp"
#include "buffer/VertexData.hpp"
#include "texture.hpp"
using namespace render::vk;
#define CONTENT_DIR "content/"
#define TEXTURES_DIR CONTENT_DIR "textures/"
CommandCenter::CommandCenter(VkDevice device, Allocator& alloc, const std::vector<VkImageView> &views,
const Pipeline& pipe, const PhysicalDeviceInfo &info, const renderOptions &opt):
device(device), indexedBufferMemory(Allocator::GetNull()), uniformBuffersMemory(Allocator::GetNull()) {
const Pipeline& pipe, const PhysicalDeviceInfo &info, const renderOptions &opt): device(device),
indexedBufferMemory(Allocator::GetNull()), sampleImageMemory(Allocator::GetNull()),
uniformBuffersMemory(Allocator::GetNull())
{
{ // Graphics command pool
vkGetDeviceQueue(device, info.queueIndices.graphicsFamily.value(), 0, &graphicsQueue);
VkCommandPoolCreateInfo poolInfo{};
@ -34,6 +40,80 @@ device(device), indexedBufferMemory(Allocator::GetNull()), uniformBuffersMemory(
FATAL("Cannot create vertex buffer");
}
}
{ // Texture sampler (const)
std::vector<unsigned char> data;
dds::header_info header;
if (dds::readDDS(TEXTURES_DIR "1024-realistic/terrain/Mapl.dds", data, header)) {
FATAL("Cannot read texture");
}
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.extent.width = header.width;
imageInfo.extent.height = header.height;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = header.mipMapCount; //TODO:
imageInfo.arrayLayers = 1;
imageInfo.format = header.format;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.flags = 0;
sampleImageMemory = alloc.createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, sampleImage, data.data(), data.size());
if(!sampleImageMemory) {
FATAL("Cannot create texture image");
}
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = sampleImage.image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = header.format;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(device, &viewInfo, nullptr, &sampleImageView) != VK_SUCCESS) {
FATAL("Failed to create texture image view!");
}
VkSamplerCreateInfo samplerInfo{};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = VK_FILTER_LINEAR;
samplerInfo.minFilter = VK_FILTER_LINEAR;
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
if (info.features.samplerAnisotropy && opt.anisotropy > 0) {
samplerInfo.anisotropyEnable = VK_TRUE;
samplerInfo.maxAnisotropy = 1 << (opt.anisotropy-1);
} else {
samplerInfo.anisotropyEnable = VK_FALSE;
samplerInfo.maxAnisotropy = 1.f;
}
samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
samplerInfo.unnormalizedCoordinates = VK_FALSE;
samplerInfo.compareEnable = VK_FALSE;
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
samplerInfo.mipLodBias = 0.0f; //TODO:
samplerInfo.minLod = 0.0f;
samplerInfo.maxLod = 0.0f;
if (vkCreateSampler(device, &samplerInfo, nullptr, &sampleSampler) != VK_SUCCESS) {
FATAL("Failed to create texture sampler!");
}
}
allocate(alloc, views, pipe, info.swapDetails.capabilities.currentExtent, opt);
}
@ -45,6 +125,11 @@ CommandCenter::~CommandCenter() {
vkDestroyBuffer(device, vertexBuffer.buffer, ALLOC);
indexedBufferMemory.reset();
vkDestroySampler(device, sampleSampler, ALLOC);
vkDestroyImageView(device, sampleImageView, ALLOC);
vkDestroyImage(device, sampleImage.image, ALLOC);
sampleImageMemory.reset();
vkDestroyCommandPool(device, graphicsPool, ALLOC);
}
#include <glm/gtc/matrix_transform.hpp>
@ -83,14 +168,16 @@ void CommandCenter::allocate(Allocator& alloc, const std::vector<VkImageView>& v
}
}
{ // Descriptor pool
VkDescriptorPoolSize poolSize{};
poolSize.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSize.descriptorCount = framebuffers.size();
std::array<VkDescriptorPoolSize, 2> poolSizes{};
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = framebuffers.size();
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[1].descriptorCount = framebuffers.size();
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = 1;
poolInfo.pPoolSizes = &poolSize;
poolInfo.poolSizeCount = poolSizes.size();
poolInfo.pPoolSizes = poolSizes.data();
poolInfo.maxSets = framebuffers.size();
poolInfo.flags = 0; //VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT
@ -117,20 +204,29 @@ void CommandCenter::allocate(Allocator& alloc, const std::vector<VkImageView>& v
bufferInfo.offset = 0;
bufferInfo.range = sizeof(buffer::vk::UniformBufferObject);
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSets[i];
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
imageInfo.imageView = sampleImageView;
imageInfo.sampler = sampleSampler;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.descriptorCount = 1;
std::array<VkWriteDescriptorSet, 2> descriptorWrites{};
descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[0].dstSet = descriptorSets[i];
descriptorWrites[0].dstBinding = 0;
descriptorWrites[0].dstArrayElement = 0;
descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrites[0].descriptorCount = 1;
descriptorWrites[0].pBufferInfo = &bufferInfo;
descriptorWrite.pBufferInfo = &bufferInfo;
descriptorWrite.pImageInfo = nullptr;
descriptorWrite.pTexelBufferView = nullptr;
descriptorWrites[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrites[1].dstSet = descriptorSets[i];
descriptorWrites[1].dstBinding = 1;
descriptorWrites[1].dstArrayElement = 0;
descriptorWrites[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptorWrites[1].descriptorCount = 1;
descriptorWrites[1].pImageInfo = &imageInfo;
vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);
vkUpdateDescriptorSets(device, descriptorWrites.size(), descriptorWrites.data(), 0, nullptr);
}
}

View File

@ -36,6 +36,11 @@ private:
Allocator::buffer_info indexBuffer;
Allocator::memory_ptr indexedBufferMemory;
Allocator::image_info sampleImage;
VkImageView sampleImageView;
VkSampler sampleSampler;
Allocator::memory_ptr sampleImageMemory;
glm::mat4 proj;
std::vector<Allocator::buffer_info> uniformBuffers;
Allocator::memory_ptr uniformBuffersMemory;

View File

@ -26,7 +26,11 @@ struct PhysicalDeviceInfo {
PhysicalDeviceInfo() {}
PhysicalDeviceInfo(GLFWwindow *window, VkPhysicalDevice device, VkSurfaceKHR surface):
window(window), device(device), surface(surface),
swapDetails(SwapChainSupportDetails::Query(device, surface)), queueIndices(QueueFamilyIndices::Query(device, surface)) { }
swapDetails(SwapChainSupportDetails::Query(device, surface)), queueIndices(QueueFamilyIndices::Query(device, surface))
{
vkGetPhysicalDeviceProperties(device, &properties);
vkGetPhysicalDeviceFeatures(device, &features);
}
VkSurfaceFormatKHR getFormat() const;
bool hasMemoryBudget() const;
@ -36,6 +40,8 @@ struct PhysicalDeviceInfo {
VkSurfaceKHR surface;
SwapChainSupportDetails swapDetails;
QueueFamilyIndices queueIndices;
VkPhysicalDeviceProperties properties;
VkPhysicalDeviceFeatures features;
std::vector<const char *> optionalExtensions;
};
}

View File

@ -7,7 +7,6 @@
#define CONTENT_DIR "content/"
#define SHADER_DIR CONTENT_DIR "shaders/"
#define TEXTURES_DIR CONTENT_DIR "textures/"
constexpr auto BLENDING = true;
@ -58,10 +57,17 @@ Pipeline::Pipeline(VkDevice device, const PhysicalDeviceInfo &info, const render
}
}
{
VkDescriptorSetLayoutBinding samplerLayoutBinding{};
samplerLayoutBinding.binding = 1;
samplerLayoutBinding.descriptorCount = 1;
samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
samplerLayoutBinding.pImmutableSamplers = nullptr;
samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
std::vector<VkDescriptorSetLayoutBinding> bindings = {buffer::vk::UniformBufferObject::getLayoutBinding(), samplerLayoutBinding};
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = 1;
std::vector<VkDescriptorSetLayoutBinding> bindings = {buffer::vk::UniformBufferObject::getLayoutBinding()};
layoutInfo.bindingCount = bindings.size();
layoutInfo.pBindings = bindings.data();
if (vkCreateDescriptorSetLayout(device, &layoutInfo, ALLOC, &descriptorSetLayout) != VK_SUCCESS) {

View File

@ -289,15 +289,8 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
uint bestScore = 0;
for(const auto& device: devices) {
uint score = 1;
VkPhysicalDeviceProperties deviceProperties;
VkPhysicalDeviceFeatures deviceFeatures;
vkGetPhysicalDeviceProperties(device, &deviceProperties);
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface);
//FIXME: if (!deviceFeatures.geometryShader) continue;
{
uint32_t availableExtensionsCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &availableExtensionsCount, nullptr);
@ -324,10 +317,17 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
}
}
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
if (infos.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
score += 10000;
score += deviceProperties.limits.maxImageDimension2D;
score += infos.properties.limits.maxImageDimension2D;
if (infos.features.geometryShader)
score += 2000;
if (infos.features.samplerAnisotropy)
score += 1000;
//TODO: check others limits
if (!infos.queueIndices.isComplete())
@ -347,9 +347,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
LOG_E("Any GPU matching requirements");
return false;
}
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(physicalInfo.device, &deviceProperties);
LOG_D("Using " << deviceProperties.deviceName);
LOG_D("Using " << physicalInfo.properties.deviceName);
}
VkDevice device;
@ -371,7 +369,8 @@ bool Renderer::Load(Window& window, const renderOptions& opt) {
}
VkPhysicalDeviceFeatures deviceFeatures{};
//TODO:
deviceFeatures.geometryShader = physicalInfo.features.geometryShader;
deviceFeatures.samplerAnisotropy = physicalInfo.features.samplerAnisotropy;
std::vector<const char*> extensions(requiredExtensions);
extensions.insert(extensions.end(), physicalInfo.optionalExtensions.begin(), physicalInfo.optionalExtensions.end());

View File

@ -10,6 +10,7 @@ namespace buffer::vk {
struct VertexData {
glm::vec2 pos;
glm::vec3 color;
glm::vec2 uv;
static VkVertexInputBindingDescription getBindingDescription() {
VkVertexInputBindingDescription description{};
@ -18,8 +19,8 @@ struct VertexData {
description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
return description;
}
static std::array<VkVertexInputAttributeDescription, 2> getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{};
static std::array<VkVertexInputAttributeDescription, 3> getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{};
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT;
@ -28,15 +29,19 @@ struct VertexData {
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[1].offset = offsetof(VertexData, color);
attributeDescriptions[2].binding = 0;
attributeDescriptions[2].location = 2;
attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[2].offset = offsetof(VertexData, uv);
return attributeDescriptions;
}
};
const std::vector<VertexData> vertices = {
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}},
{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}},
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}},
{{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}}
{{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
{{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
{{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
{{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}
};
const std::vector<uint16_t> indices = {
0, 1, 2, 2, 3, 0

View File

@ -0,0 +1,75 @@
#include "texture.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cassert>
#include <cmath>
#include <iostream>
#include <array>
#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
VkResult render::vk::dds::readDDS(const std::string& imagepath, std::vector<unsigned char>& data, header_info& info) {
unsigned char header[124];
FILE *fp;
/* try to open the file */
fp = fopen(imagepath.c_str(), "rb");
if (fp == NULL){
printf("%s could not be opened.\n", imagepath.c_str()); getchar();
return VK_ERROR_INVALID_DEVICE_ADDRESS_EXT;
}
/* verify the type of file */
char filecode[4];
fread(filecode, 1, 4, fp);
if (strncmp(filecode, "DDS ", 4) != 0) {
fclose(fp);
return VK_ERROR_INVALID_DEVICE_ADDRESS_EXT;
}
/* get the surface desc */
fread(&header, 124, 1, fp);
info.height = *(unsigned int*)&(header[8 ]);
info.width = *(unsigned int*)&(header[12]);
unsigned int linearSize = *(unsigned int*)&(header[16]);
info.mipMapCount = *(unsigned int*)&(header[24]);
unsigned int fourCC = *(unsigned int*)&(header[80]);
/* how big is it going to be including all mipmaps? */
unsigned int bufsize = info.mipMapCount > 1 ? linearSize * 2 : linearSize;
data.resize(bufsize);
fread(data.data(), 1, bufsize, fp);
/* close the file pointer */
fclose(fp);
switch(fourCC)
{
case FOURCC_DXT1:
info.format = VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
break;
case FOURCC_DXT3:
info.format = VK_FORMAT_BC2_SRGB_BLOCK;
break;
case FOURCC_DXT5:
info.format = VK_FORMAT_BC3_SRGB_BLOCK;
break;
//MAYBE: VK_FORMAT_BC6H_SFLOAT_BLOCK
default:
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
#if FALSE
glTextureParameteri(textureID, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST);
glTextureParameteri(textureID, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST);
TODO: glGenerateTextureMipmap(textureID);
#endif
return VK_SUCCESS;
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <string>
#include <vector>
#include <array>
#include <volk.h>
namespace render::vk::dds {
struct header_info {
unsigned int height;
unsigned int width;
unsigned int mipMapCount;
VkFormat format;
};
VkResult readDDS(const std::string& imagepath, std::vector<unsigned char>& data, header_info& info);
}