holy shit an image
This commit is contained in:
parent
f4fcfd3fda
commit
b97a9e2b7b
7988
include/stb_image.h
Normal file
7988
include/stb_image.h
Normal file
File diff suppressed because it is too large
Load diff
12
meson.build
12
meson.build
|
@ -24,16 +24,6 @@ common_cpp_args = [
|
|||
|
||||
add_project_arguments(cpp.get_supported_arguments(common_cpp_args), language: 'cpp')
|
||||
|
||||
source_file_names = [
|
||||
'src/main.cpp',
|
||||
]
|
||||
|
||||
sources = []
|
||||
|
||||
foreach file : source_file_names
|
||||
sources += files(file)
|
||||
endforeach
|
||||
|
||||
deps = [
|
||||
dependency('fmt', include_type: 'system'),
|
||||
dependency('glfw3', include_type: 'system'),
|
||||
|
@ -43,7 +33,7 @@ deps = [
|
|||
|
||||
executable(
|
||||
'graphics-test',
|
||||
sources,
|
||||
sources: files('src/main.cpp'),
|
||||
include_directories: include_directories('include', is_system: true),
|
||||
dependencies: deps,
|
||||
)
|
338
src/main.cpp
338
src/main.cpp
|
@ -1,12 +1,13 @@
|
|||
#include <chrono>
|
||||
#include <fmt/format.h>
|
||||
#include <fstream>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
|
||||
#define VK_ENABLE_BETA_EXTENSIONS
|
||||
|
@ -43,24 +44,26 @@ constexpr bool enableValidationLayers = true;
|
|||
struct Vertex {
|
||||
glm::vec2 pos;
|
||||
glm::vec3 color;
|
||||
glm::vec2 tex_coord;
|
||||
|
||||
static fn getBindingDescription() -> vk::VertexInputBindingDescription {
|
||||
return { .binding = 0, .stride = sizeof(Vertex), .inputRate = vk::VertexInputRate::eVertex };
|
||||
}
|
||||
|
||||
static fn getAttributeDescriptions() -> std::array<vk::VertexInputAttributeDescription, 2> {
|
||||
static fn getAttributeDescriptions() -> std::array<vk::VertexInputAttributeDescription, 3> {
|
||||
return {
|
||||
vk::VertexInputAttributeDescription { 0, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, pos) },
|
||||
vk::VertexInputAttributeDescription { 1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color) }
|
||||
{ { 0, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, pos) },
|
||||
{ 1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color) },
|
||||
{ 2, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, tex_coord) } }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
constexpr std::array<Vertex, 4> 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 }, { 1.0F, 0.0F } },
|
||||
{ { 0.5F, -0.5F }, { 0.0F, 1.0F, 0.0F }, { 0.0F, 0.0F } },
|
||||
{ { 0.5F, 0.5F }, { 0.0F, 0.0F, 1.0F }, { 0.0F, 1.0F } },
|
||||
{ { -0.5F, 0.5F }, { 1.0F, 1.0F, 1.0F }, { 1.0F, 1.0F } } }
|
||||
};
|
||||
|
||||
constexpr std::array<u16, 6> indices = { 0, 1, 2, 2, 3, 0 };
|
||||
|
@ -102,6 +105,11 @@ class VulkanApp {
|
|||
|
||||
vk::UniqueCommandPool mCommandPool;
|
||||
|
||||
vk::UniqueImage mTextureImage;
|
||||
vk::UniqueDeviceMemory mTextureImageMemory;
|
||||
vk::UniqueImageView mTextureImageView;
|
||||
vk::UniqueSampler mTextureSampler;
|
||||
|
||||
vk::UniqueBuffer mVertexBuffer;
|
||||
vk::UniqueDeviceMemory mVertexBufferMemory;
|
||||
vk::UniqueBuffer mIndexBuffer;
|
||||
|
@ -190,6 +198,9 @@ class VulkanApp {
|
|||
createGraphicsPipeline();
|
||||
createFramebuffers();
|
||||
createCommandPool();
|
||||
createTextureImage();
|
||||
createTextureImageView();
|
||||
createTextureSampler();
|
||||
createVertexBuffer();
|
||||
createIndexBuffer();
|
||||
createUniformBuffers();
|
||||
|
@ -341,7 +352,9 @@ class VulkanApp {
|
|||
queueCreateInfos.emplace_back(queueCreateInfo);
|
||||
}
|
||||
|
||||
vk::PhysicalDeviceFeatures deviceFeatures;
|
||||
vk::PhysicalDeviceFeatures deviceFeatures {
|
||||
.samplerAnisotropy = vk::True,
|
||||
};
|
||||
|
||||
vk::DeviceCreateInfo createInfo { .queueCreateInfoCount = static_cast<u32>(queueCreateInfos.size()),
|
||||
.pQueueCreateInfos = queueCreateInfos.data(),
|
||||
|
@ -466,9 +479,19 @@ class VulkanApp {
|
|||
.pImmutableSamplers = nullptr,
|
||||
};
|
||||
|
||||
vk::DescriptorSetLayoutBinding samplerLayoutBinding {
|
||||
.binding = 1,
|
||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||
.pImmutableSamplers = nullptr,
|
||||
};
|
||||
|
||||
std::array<vk::DescriptorSetLayoutBinding, 2> bindings = { uboLayoutBinding, samplerLayoutBinding };
|
||||
|
||||
vk::DescriptorSetLayoutCreateInfo layoutInfo {
|
||||
.bindingCount = 1,
|
||||
.pBindings = &uboLayoutBinding,
|
||||
.bindingCount = static_cast<u32>(bindings.size()),
|
||||
.pBindings = bindings.data(),
|
||||
};
|
||||
|
||||
mDescriptorSetLayout = mDevice->createDescriptorSetLayoutUnique(layoutInfo);
|
||||
|
@ -497,7 +520,7 @@ class VulkanApp {
|
|||
fragShaderStageInfo };
|
||||
|
||||
vk::VertexInputBindingDescription bindingDescription = Vertex::getBindingDescription();
|
||||
std::array<vk::VertexInputAttributeDescription, 2> attributeDescriptions =
|
||||
std::array<vk::VertexInputAttributeDescription, 3> attributeDescriptions =
|
||||
Vertex::getAttributeDescriptions();
|
||||
|
||||
vk::PipelineVertexInputStateCreateInfo vertexInputInfo {
|
||||
|
@ -615,6 +638,213 @@ class VulkanApp {
|
|||
mCommandPool = mDevice->createCommandPoolUnique(poolInfo);
|
||||
}
|
||||
|
||||
fn createTextureImage() -> void {
|
||||
i32 texWidth = 0, texHeight = 0, texChannels = 0;
|
||||
stbi_uc* pixels =
|
||||
stbi_load("src/textures/texture.jpg", &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
|
||||
|
||||
vk::DeviceSize imageSize =
|
||||
static_cast<vk::DeviceSize>(texWidth) * static_cast<vk::DeviceSize>(texHeight) * 4;
|
||||
|
||||
if (!pixels)
|
||||
throw std::runtime_error("Failed to load texture image!");
|
||||
|
||||
vk::UniqueBuffer stagingBuffer;
|
||||
vk::UniqueDeviceMemory stagingBufferMemory;
|
||||
|
||||
createBuffer(
|
||||
imageSize,
|
||||
vk::BufferUsageFlagBits::eTransferSrc,
|
||||
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent,
|
||||
stagingBuffer,
|
||||
stagingBufferMemory
|
||||
);
|
||||
|
||||
copyData(stagingBufferMemory.get(), imageSize, pixels);
|
||||
|
||||
stbi_image_free(pixels);
|
||||
|
||||
createImage(
|
||||
static_cast<u32>(texWidth),
|
||||
static_cast<u32>(texHeight),
|
||||
vk::Format::eR8G8B8A8Srgb,
|
||||
vk::ImageTiling::eOptimal,
|
||||
vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled,
|
||||
vk::MemoryPropertyFlagBits::eDeviceLocal,
|
||||
mTextureImage,
|
||||
mTextureImageMemory
|
||||
);
|
||||
|
||||
transitionImageLayout(
|
||||
mTextureImage.get(),
|
||||
vk::Format::eR8G8B8A8Srgb,
|
||||
vk::ImageLayout::eUndefined,
|
||||
vk::ImageLayout::eTransferDstOptimal
|
||||
);
|
||||
|
||||
copyBufferToImage(
|
||||
stagingBuffer.get(), mTextureImage.get(), static_cast<u32>(texWidth), static_cast<u32>(texHeight)
|
||||
);
|
||||
|
||||
transitionImageLayout(
|
||||
mTextureImage.get(),
|
||||
vk::Format::eR8G8B8A8Srgb,
|
||||
vk::ImageLayout::eTransferDstOptimal,
|
||||
vk::ImageLayout::eShaderReadOnlyOptimal
|
||||
);
|
||||
}
|
||||
|
||||
fn createTextureImageView() -> void {
|
||||
mTextureImageView =
|
||||
createImageView(mTextureImage.get(), vk::Format::eR8G8B8A8Srgb, vk::ImageAspectFlagBits::eColor);
|
||||
}
|
||||
|
||||
fn createTextureSampler() -> void {
|
||||
vk::PhysicalDeviceProperties properties = mPhysicalDevice.getProperties();
|
||||
|
||||
vk::SamplerCreateInfo samplerInfo {
|
||||
.magFilter = vk::Filter::eLinear,
|
||||
.minFilter = vk::Filter::eLinear,
|
||||
.mipmapMode = vk::SamplerMipmapMode::eLinear,
|
||||
.addressModeU = vk::SamplerAddressMode::eRepeat,
|
||||
.addressModeV = vk::SamplerAddressMode::eRepeat,
|
||||
.addressModeW = vk::SamplerAddressMode::eRepeat,
|
||||
.mipLodBias = 0.0F,
|
||||
.anisotropyEnable = vk::False,
|
||||
.maxAnisotropy = properties.limits.maxSamplerAnisotropy,
|
||||
.compareEnable = vk::False,
|
||||
.compareOp = vk::CompareOp::eAlways,
|
||||
.minLod = 0.0F,
|
||||
.maxLod = 0.0F,
|
||||
.borderColor = vk::BorderColor::eIntOpaqueBlack,
|
||||
.unnormalizedCoordinates = vk::False,
|
||||
};
|
||||
|
||||
mTextureSampler = mDevice->createSamplerUnique(samplerInfo);
|
||||
}
|
||||
|
||||
fn createImageView(vk::Image image, vk::Format format, vk::ImageAspectFlags aspectFlags)
|
||||
-> vk::UniqueImageView {
|
||||
vk::ImageViewCreateInfo viewInfo {
|
||||
.image = image, .viewType = vk::ImageViewType::e2D, .format = format, .subresourceRange = {
|
||||
.aspectMask = aspectFlags,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
}
|
||||
};
|
||||
|
||||
return mDevice->createImageViewUnique(viewInfo);
|
||||
}
|
||||
|
||||
fn createImage(
|
||||
u32 width,
|
||||
u32 height,
|
||||
vk::Format format,
|
||||
vk::ImageTiling tiling,
|
||||
vk::ImageUsageFlags usage,
|
||||
vk::MemoryPropertyFlags properties,
|
||||
vk::UniqueImage& image,
|
||||
vk::UniqueDeviceMemory& imageMemory
|
||||
) -> void {
|
||||
vk::ImageCreateInfo imageInfo {
|
||||
.imageType = vk::ImageType::e2D,
|
||||
.format = format,
|
||||
.extent = { .width = width, .height = height, .depth = 1 },
|
||||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
.samples = vk::SampleCountFlagBits::e1,
|
||||
.tiling = tiling,
|
||||
.usage = usage,
|
||||
.sharingMode = vk::SharingMode::eExclusive,
|
||||
.initialLayout = vk::ImageLayout::eUndefined,
|
||||
};
|
||||
|
||||
image = mDevice->createImageUnique(imageInfo);
|
||||
|
||||
vk::MemoryRequirements memRequirements = mDevice->getImageMemoryRequirements(image.get());
|
||||
|
||||
vk::MemoryAllocateInfo allocInfo {
|
||||
.allocationSize = memRequirements.size,
|
||||
.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties),
|
||||
};
|
||||
|
||||
imageMemory = mDevice->allocateMemoryUnique(allocInfo);
|
||||
|
||||
mDevice->bindImageMemory(image.get(), imageMemory.get(), 0);
|
||||
}
|
||||
|
||||
fn transitionImageLayout(
|
||||
vk::Image image,
|
||||
vk::Format format,
|
||||
vk::ImageLayout oldLayout,
|
||||
vk::ImageLayout newLayout
|
||||
) -> void {
|
||||
vk::UniqueCommandBuffer commandBuffer = beginSingleTimeCommands();
|
||||
|
||||
vk::ImageMemoryBarrier barrier {
|
||||
.srcAccessMask = { },
|
||||
.dstAccessMask = { },
|
||||
.oldLayout = oldLayout,
|
||||
.newLayout = newLayout,
|
||||
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
||||
.image = image,
|
||||
// clang-format off
|
||||
.subresourceRange = { .aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1 },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
vk::PipelineStageFlags sourceStage;
|
||||
vk::PipelineStageFlags destinationStage;
|
||||
|
||||
if (oldLayout == vk::ImageLayout::eUndefined && newLayout == vk::ImageLayout::eTransferDstOptimal) {
|
||||
barrier.srcAccessMask = {};
|
||||
barrier.dstAccessMask = vk::AccessFlagBits::eTransferWrite;
|
||||
|
||||
sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
|
||||
destinationStage = vk::PipelineStageFlagBits::eTransfer;
|
||||
} else if (oldLayout == vk::ImageLayout::eTransferDstOptimal &&
|
||||
newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) {
|
||||
barrier.srcAccessMask = vk::AccessFlagBits::eTransferWrite;
|
||||
barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead;
|
||||
|
||||
sourceStage = vk::PipelineStageFlagBits::eTransfer;
|
||||
destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
|
||||
} else {
|
||||
throw std::invalid_argument("Unsupported layout transition!");
|
||||
}
|
||||
|
||||
commandBuffer->pipelineBarrier(sourceStage, destinationStage, {}, {}, {}, barrier);
|
||||
|
||||
endSingleTimeCommands(std::move(commandBuffer));
|
||||
}
|
||||
|
||||
fn copyBufferToImage(vk::Buffer buffer, vk::Image image, u32 width, u32 height) -> void {
|
||||
vk::UniqueCommandBuffer commandBuffer = beginSingleTimeCommands();
|
||||
|
||||
vk::BufferImageCopy region {
|
||||
.bufferOffset = 0,
|
||||
.bufferRowLength = 0,
|
||||
.bufferImageHeight = 0,
|
||||
.imageSubresource = { .aspectMask = vk::ImageAspectFlagBits::eColor,
|
||||
.mipLevel = 0,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1 },
|
||||
.imageOffset = { 0, 0, 0 },
|
||||
.imageExtent = { width, height, 1 },
|
||||
};
|
||||
|
||||
commandBuffer->copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, 1, ®ion);
|
||||
|
||||
endSingleTimeCommands(std::move(commandBuffer));
|
||||
}
|
||||
|
||||
fn createVertexBuffer() -> void {
|
||||
vk::DeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();
|
||||
|
||||
|
@ -629,9 +859,7 @@ class VulkanApp {
|
|||
stagingBufferMemory
|
||||
);
|
||||
|
||||
void* data = mDevice->mapMemory(stagingBufferMemory.get(), 0, bufferSize);
|
||||
memcpy(data, vertices.data(), static_cast<usize>(bufferSize));
|
||||
mDevice->unmapMemory(stagingBufferMemory.get());
|
||||
copyData(stagingBufferMemory.get(), bufferSize, vertices.data());
|
||||
|
||||
createBuffer(
|
||||
bufferSize,
|
||||
|
@ -661,9 +889,7 @@ class VulkanApp {
|
|||
stagingBufferMemory
|
||||
);
|
||||
|
||||
void* data = mDevice->mapMemory(stagingBufferMemory.get(), 0, bufferSize);
|
||||
memcpy(data, indices.data(), static_cast<usize>(bufferSize));
|
||||
mDevice->unmapMemory(stagingBufferMemory.get());
|
||||
copyData(stagingBufferMemory.get(), bufferSize, indices.data());
|
||||
|
||||
createBuffer(
|
||||
bufferSize,
|
||||
|
@ -700,15 +926,15 @@ class VulkanApp {
|
|||
}
|
||||
|
||||
fn createDescriptorPool() -> void {
|
||||
vk::DescriptorPoolSize poolSize {
|
||||
.type = vk::DescriptorType::eUniformBuffer,
|
||||
.descriptorCount = static_cast<u32>(MAX_FRAMES_IN_FLIGHT),
|
||||
std::array<vk::DescriptorPoolSize, 2> poolSizes = {
|
||||
{ { .type = vk::DescriptorType::eUniformBuffer, .descriptorCount = MAX_FRAMES_IN_FLIGHT },
|
||||
{ .type = vk::DescriptorType::eCombinedImageSampler, .descriptorCount = MAX_FRAMES_IN_FLIGHT } },
|
||||
};
|
||||
|
||||
vk::DescriptorPoolCreateInfo poolInfo {
|
||||
.maxSets = static_cast<u32>(MAX_FRAMES_IN_FLIGHT),
|
||||
.poolSizeCount = 1,
|
||||
.pPoolSizes = &poolSize,
|
||||
.maxSets = MAX_FRAMES_IN_FLIGHT,
|
||||
.poolSizeCount = static_cast<u32>(poolSizes.size()),
|
||||
.pPoolSizes = poolSizes.data(),
|
||||
};
|
||||
|
||||
mDescriptorPool = mDevice->createDescriptorPoolUnique(poolInfo);
|
||||
|
@ -732,16 +958,31 @@ class VulkanApp {
|
|||
.range = sizeof(UniformBufferObject),
|
||||
};
|
||||
|
||||
vk::WriteDescriptorSet descriptorWrite {
|
||||
.dstSet = mDescriptorSets[i],
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||
.pBufferInfo = &bufferInfo,
|
||||
vk::DescriptorImageInfo imageInfo {
|
||||
.sampler = mTextureSampler.get(),
|
||||
.imageView = mTextureImageView.get(),
|
||||
.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||
};
|
||||
|
||||
mDevice->updateDescriptorSets(1, &descriptorWrite, 0, nullptr);
|
||||
std::array<vk::WriteDescriptorSet, 2> descriptorWrites = {
|
||||
{ {
|
||||
.dstSet = mDescriptorSets[i],
|
||||
.dstBinding = 0,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||
.pBufferInfo = &bufferInfo,
|
||||
}, {
|
||||
.dstSet = mDescriptorSets[i],
|
||||
.dstBinding = 1,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = vk::DescriptorType::eCombinedImageSampler,
|
||||
.pImageInfo = &imageInfo,
|
||||
} }
|
||||
};
|
||||
|
||||
mDevice->updateDescriptorSets(descriptorWrites, {});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -772,7 +1013,7 @@ class VulkanApp {
|
|||
mDevice->bindBufferMemory(buffer.get(), bufferMemory.get(), 0);
|
||||
}
|
||||
|
||||
fn copyBuffer(vk::Buffer srcBuffer, vk::Buffer dstBuffer, vk::DeviceSize deviceSize) -> void {
|
||||
fn beginSingleTimeCommands() -> vk::UniqueCommandBuffer {
|
||||
vk::CommandBufferAllocateInfo allocInfo {
|
||||
.commandPool = mCommandPool.get(),
|
||||
.level = vk::CommandBufferLevel::ePrimary,
|
||||
|
@ -785,10 +1026,10 @@ class VulkanApp {
|
|||
|
||||
commandBuffer->begin(beginInfo);
|
||||
|
||||
vk::BufferCopy copyRegion { .size = deviceSize };
|
||||
|
||||
commandBuffer->copyBuffer(srcBuffer, dstBuffer, 1, ©Region);
|
||||
return commandBuffer;
|
||||
}
|
||||
|
||||
fn endSingleTimeCommands(vk::UniqueCommandBuffer commandBuffer) -> void {
|
||||
commandBuffer->end();
|
||||
|
||||
vk::SubmitInfo submitInfo { .commandBufferCount = 1, .pCommandBuffers = &commandBuffer.get() };
|
||||
|
@ -797,6 +1038,22 @@ class VulkanApp {
|
|||
mGraphicsQueue.waitIdle();
|
||||
}
|
||||
|
||||
fn copyData(vk::DeviceMemory stagingBufferMemory, vk::DeviceSize bufferSize, const void* src) -> void {
|
||||
void* data = mDevice->mapMemory(stagingBufferMemory, 0, bufferSize);
|
||||
memcpy(data, src, static_cast<usize>(bufferSize));
|
||||
mDevice->unmapMemory(stagingBufferMemory);
|
||||
}
|
||||
|
||||
fn copyBuffer(vk::Buffer srcBuffer, vk::Buffer dstBuffer, vk::DeviceSize deviceSize) -> void {
|
||||
vk::UniqueCommandBuffer commandBuffer = beginSingleTimeCommands();
|
||||
|
||||
vk::BufferCopy copyRegion { .size = deviceSize };
|
||||
|
||||
commandBuffer->copyBuffer(srcBuffer, dstBuffer, 1, ©Region);
|
||||
|
||||
endSingleTimeCommands(std::move(commandBuffer));
|
||||
}
|
||||
|
||||
fn findMemoryType(u32 typeFilter, vk::MemoryPropertyFlags properties) -> u32 {
|
||||
vk::PhysicalDeviceMemoryProperties memProperties = mPhysicalDevice.getMemoryProperties();
|
||||
|
||||
|
@ -1052,7 +1309,10 @@ class VulkanApp {
|
|||
swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.present_modes.empty();
|
||||
}
|
||||
|
||||
return qfIndices.isComplete() && extensionsSupported && swapChainAdequate;
|
||||
vk::PhysicalDeviceFeatures supportedFeatures = device.getFeatures();
|
||||
|
||||
return qfIndices.isComplete() && extensionsSupported && swapChainAdequate &&
|
||||
supportedFeatures.samplerAnisotropy;
|
||||
}
|
||||
|
||||
static fn checkDeviceExtensionSupport(vk::PhysicalDevice device) -> bool {
|
||||
|
|
Binary file not shown.
|
@ -1,9 +1,12 @@
|
|||
#version 450
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -8,10 +8,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;
|
||||
}
|
||||
|
|
Binary file not shown.
BIN
src/textures/texture.jpg
Normal file
BIN
src/textures/texture.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 75 KiB |
Loading…
Reference in a new issue