完成gltfTexture重构
parent
e43f2e1aac
commit
7f3056d2fe
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
SET(PLUMAGE_RENDER "${CMAKE_CURRENT_SOURCE_DIR}/render")
|
SET(PLUMAGE_RENDER "${CMAKE_CURRENT_SOURCE_DIR}/render")
|
||||||
message("working path ${PLUMAGE_RENDER}")
|
message("working path ${PLUMAGE_RENDER}")
|
||||||
|
|
||||||
|
@ -11,6 +11,18 @@ set(MAIN_FILE
|
||||||
set(GLTF_MODEL_LOADER
|
set(GLTF_MODEL_LOADER
|
||||||
"${PLUMAGE_RENDER}/glTFBoundingBox.h"
|
"${PLUMAGE_RENDER}/glTFBoundingBox.h"
|
||||||
"${PLUMAGE_RENDER}/glTFBoundingBox.cpp"
|
"${PLUMAGE_RENDER}/glTFBoundingBox.cpp"
|
||||||
|
"${PLUMAGE_RENDER}/glTFTexture.h"
|
||||||
|
"${PLUMAGE_RENDER}/glTFTexture.cpp"
|
||||||
|
"render/glTFModel.h"
|
||||||
|
"render/glTFModel.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(VULKAN_BASE
|
||||||
|
"render/VulkanBase_Common.h"
|
||||||
|
"render/VulkanDevice.h"
|
||||||
|
"render/VulkanDevice.cpp"
|
||||||
|
"render/VulkanTextureSampler.h"
|
||||||
|
"render/VulkanTextureSampler.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
# wayland requires additional source files
|
# wayland requires additional source files
|
||||||
|
@ -27,6 +39,8 @@ ENDIF()
|
||||||
# Add optional readme / tutorial
|
# Add optional readme / tutorial
|
||||||
#file(GLOB README_FILES "${HOMEWORK_FOLDER}/*.md")
|
#file(GLOB README_FILES "${HOMEWORK_FOLDER}/*.md")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
include_directories(${3rdParty_gli_path})
|
include_directories(${3rdParty_gli_path})
|
||||||
include_directories(${3rdParty_glm_path})
|
include_directories(${3rdParty_glm_path})
|
||||||
include_directories(${3rdParty_imgui_path})
|
include_directories(${3rdParty_imgui_path})
|
||||||
|
@ -43,10 +57,11 @@ if(WIN32)
|
||||||
add_executable(${RenderName} WIN32 ${SHADERS_GLSL} ${SHADERS_HLSL}
|
add_executable(${RenderName} WIN32 ${SHADERS_GLSL} ${SHADERS_HLSL}
|
||||||
${MAIN_FILE}
|
${MAIN_FILE}
|
||||||
${GLTF_MODEL_LOADER}
|
${GLTF_MODEL_LOADER}
|
||||||
"render/glTFModel.h"
|
${VULKAN_BASE}
|
||||||
"render/glTFModel.cpp"
|
|
||||||
"render/renderFoundation.h"
|
"render/renderFoundation.h"
|
||||||
"render/renderFoundation.cpp" )
|
"render/renderFoundation.cpp"
|
||||||
|
)
|
||||||
target_link_libraries(${RenderName} base ${Vulkan_LIBRARY} ${WINLIBS})
|
target_link_libraries(${RenderName} base ${Vulkan_LIBRARY} ${WINLIBS})
|
||||||
endif()
|
endif()
|
||||||
set_target_properties(${RenderName} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
set_target_properties(${RenderName} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||||
|
@ -56,13 +71,14 @@ if(RESOURCE_INSTALL_DIR)
|
||||||
install(TARGETS ${RenderName} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
install(TARGETS ${RenderName} DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# 后续移动到动态库后删除
|
||||||
#if(WIN32)
|
if(WIN32)
|
||||||
# target_compile_definitions(MyLib PRIVATE MYLIB_EXPORTS)
|
target_compile_definitions(${RenderName} PRIVATE VULKANBASE_STATIC_BUILD)
|
||||||
#endif(UNIX AND NOT APPLE) # Linux及类似系统
|
target_compile_definitions(${RenderName} PRIVATE GLTFLOADER_STATIC_BUILD)
|
||||||
# add_compile_options(-fvisibility=hidden)
|
elseif(UNIX AND NOT APPLE) # Linux及类似系统
|
||||||
# add_compile_options(-fvisibility-inlines-hidden)
|
add_compile_options(-fvisibility=hidden)
|
||||||
#endif()
|
add_compile_options(-fvisibility-inlines-hidden)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
file(GLOB BASE_SRC "*.cpp" "*.h" "${3rdParty_imgui_path}/*.cpp" )
|
file(GLOB BASE_SRC "*.cpp" "*.h" "${3rdParty_imgui_path}/*.cpp" )
|
||||||
|
|
||||||
|
|
||||||
include_directories(${3rdParty_ktx_path})
|
include_directories(${3rdParty_ktx_path})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* Vulkan device class
|
* Vulkan device class
|
||||||
*
|
*
|
||||||
* Encapsulates a physical Vulkan device and it's logical representation
|
* Encapsulates a physical Vulkan device and it's logical representation
|
||||||
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include "VulkanTools.h"
|
#include "VulkanTools.h"
|
||||||
|
|
||||||
|
|
||||||
|
/// @brief 已单独剥离,等待删除
|
||||||
namespace vks
|
namespace vks
|
||||||
{
|
{
|
||||||
struct VulkanDevice
|
struct VulkanDevice
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "vulkan/vulkan.h"
|
#include "vulkan/vulkan.h"
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/// 命名空间宏
|
||||||
|
#define VULKANBASE_NAMESPACE_BEGIN namespace VulkanBase {
|
||||||
|
#define VULKANBASE_NAMESPACE_END }
|
||||||
|
|
||||||
|
/// windows 导入导出宏,GLTFLOADER_EXPORTS将在cmake中定义
|
||||||
|
/// unix-like 下提供符号可见性控制
|
||||||
|
#ifdef VULKANBASE_STATIC_BUILD
|
||||||
|
#define VULKANBASE_API
|
||||||
|
#define VULKANBASE_LOCAL
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef VULKANBASE_EXPORTS
|
||||||
|
#define VULKANBASE_API __declspec(dllexport)
|
||||||
|
#define VULKANBASE_LOCAL
|
||||||
|
#else
|
||||||
|
#define VULKANBASE_API __declspec(dllimport)
|
||||||
|
#define VULKANBASE_LOCAL
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if __GNUC__ >= 4 || defined(__clang__)
|
||||||
|
#define VULKANBASE_API __attribute__ ((visibility ("default")))
|
||||||
|
#define VULKANBASE_LOCAL __attribute__ ((visibility ("hidden")))
|
||||||
|
#else
|
||||||
|
#define VULKANBASE_API
|
||||||
|
#define VULKANBASE_LOCAL
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -0,0 +1,213 @@
|
||||||
|
#include "VulkanDevice.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <VulkanTools.h>
|
||||||
|
|
||||||
|
VULKANBASE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
VulkanDevice::VulkanDevice()
|
||||||
|
:m_commandPool(VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanDevice::VulkanDevice(VkPhysicalDevice physicalDevice)
|
||||||
|
{
|
||||||
|
/// 检查物理设备是否存在,后续使用log方式记录
|
||||||
|
assert(physicalDevice);
|
||||||
|
m_physicalDevice = physicalDevice;
|
||||||
|
|
||||||
|
/// 获取设备信息
|
||||||
|
vkGetPhysicalDeviceProperties(physicalDevice, &m_properties);
|
||||||
|
/// 获取设备支持的功能
|
||||||
|
vkGetPhysicalDeviceFeatures(physicalDevice, &m_features);
|
||||||
|
/// 获取设备内存信息,用于创建内存
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &m_memoryProperties);
|
||||||
|
/// 队列族信息,用于设备创建时获取设置获取的队列
|
||||||
|
uint32_t queueFamilyCount;
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr);
|
||||||
|
/// 检查设备队列族数量,必须大于0
|
||||||
|
assert(queueFamilyCount > 0);
|
||||||
|
m_queueFamilyProperties.resize(queueFamilyCount);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, m_queueFamilyProperties.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VulkanDevice::~VulkanDevice()
|
||||||
|
{
|
||||||
|
if (m_commandPool) {
|
||||||
|
vkDestroyCommandPool(m_logicalDevice, m_commandPool, nullptr);
|
||||||
|
}
|
||||||
|
if (m_logicalDevice) {
|
||||||
|
vkDestroyDevice(m_logicalDevice, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDevice VulkanDevice::getLogicalDevice()
|
||||||
|
{
|
||||||
|
return m_logicalDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPhysicalDevice VulkanDevice::getPhysicalDevice()
|
||||||
|
{
|
||||||
|
return m_physicalDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t VulkanDevice::getMemoryType(uint32_t typeBits, VkMemoryPropertyFlags properties, VkBool32* memTypeFound = nullptr)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < m_memoryProperties.memoryTypeCount; i++) {
|
||||||
|
if ((typeBits & 1) == 1) {
|
||||||
|
if ((m_memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) {
|
||||||
|
if (memTypeFound) {
|
||||||
|
*memTypeFound = true;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typeBits >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memTypeFound) {
|
||||||
|
*memTypeFound = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Could not find a matching memory type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t VulkanDevice::getQueueFamilyIndex(VkQueueFlagBits queueFlags)
|
||||||
|
{
|
||||||
|
/// 获取支持计算的队列组索引
|
||||||
|
if (queueFlags & VK_QUEUE_COMPUTE_BIT)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < static_cast<uint32_t>(m_queueFamilyProperties.size()); i++) {
|
||||||
|
if ((m_queueFamilyProperties[i].queueFlags & queueFlags) && ((m_queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
|
||||||
|
return i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 对于其他的队列类型,如果当前没有单独的计算队列,返回支持标志类型的第一个队列
|
||||||
|
for (uint32_t i = 0; i < static_cast<uint32_t>(m_queueFamilyProperties.size()); i++) {
|
||||||
|
if (m_queueFamilyProperties[i].queueFlags & queueFlags) {
|
||||||
|
return i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("Could not find a matching queue family index");
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult VulkanDevice::createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, VkBuffer* buffer, VkDeviceMemory* memory, void* data = nullptr)
|
||||||
|
{
|
||||||
|
// 创建buffer句柄
|
||||||
|
VkBufferCreateInfo bufferCreateInfo{};
|
||||||
|
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
bufferCreateInfo.usage = usageFlags;
|
||||||
|
bufferCreateInfo.size = size;
|
||||||
|
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
VK_CHECK_RESULT(vkCreateBuffer(m_logicalDevice, &bufferCreateInfo, nullptr, buffer));
|
||||||
|
|
||||||
|
// 创建buffer的设备内存分配信息
|
||||||
|
VkMemoryRequirements memReqs;
|
||||||
|
VkMemoryAllocateInfo memAlloc{};
|
||||||
|
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
vkGetBufferMemoryRequirements(m_logicalDevice, *buffer, &memReqs);
|
||||||
|
memAlloc.allocationSize = memReqs.size;
|
||||||
|
/// 获取符合buffer的设备内存类型索引
|
||||||
|
memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags);
|
||||||
|
VK_CHECK_RESULT(vkAllocateMemory(m_logicalDevice, &memAlloc, nullptr, memory));
|
||||||
|
|
||||||
|
// 如何buffer指针已经存在,复制或者映射该buffer
|
||||||
|
if (data != nullptr)
|
||||||
|
{
|
||||||
|
void* mapped;
|
||||||
|
VK_CHECK_RESULT(vkMapMemory(m_logicalDevice, *memory, 0, size, 0, &mapped));
|
||||||
|
memcpy(mapped, data, size);
|
||||||
|
// 如果host coherency 未设置, 对buffer进行flush,让设备侧可见
|
||||||
|
if ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
|
||||||
|
{
|
||||||
|
VkMappedMemoryRange mappedRange{};
|
||||||
|
mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||||
|
mappedRange.memory = *memory;
|
||||||
|
mappedRange.offset = 0;
|
||||||
|
mappedRange.size = size;
|
||||||
|
vkFlushMappedMemoryRanges(m_logicalDevice, 1, &mappedRange);
|
||||||
|
}
|
||||||
|
vkUnmapMemory(m_logicalDevice, *memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绑定设备内存到buffer object
|
||||||
|
VK_CHECK_RESULT(vkBindBufferMemory(m_logicalDevice, *buffer, *memory, 0));
|
||||||
|
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkCommandPool VulkanDevice::createCommandPool(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
|
||||||
|
{
|
||||||
|
/// 创建命令缓冲池
|
||||||
|
VkCommandPoolCreateInfo cmdPoolInfo = {};
|
||||||
|
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||||
|
cmdPoolInfo.queueFamilyIndex = queueFamilyIndex;
|
||||||
|
cmdPoolInfo.flags = createFlags;
|
||||||
|
VkCommandPool cmdPool;
|
||||||
|
VK_CHECK_RESULT(vkCreateCommandPool(m_logicalDevice, &cmdPoolInfo, nullptr, &cmdPool));
|
||||||
|
return cmdPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkCommandBuffer VulkanDevice::createCommandBuffer(VkCommandBufferLevel level, bool begin = false)
|
||||||
|
{
|
||||||
|
VkCommandBufferAllocateInfo cmdBufAllocateInfo{};
|
||||||
|
cmdBufAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
cmdBufAllocateInfo.commandPool = m_commandPool;
|
||||||
|
cmdBufAllocateInfo.level = level;
|
||||||
|
cmdBufAllocateInfo.commandBufferCount = 1;
|
||||||
|
|
||||||
|
VkCommandBuffer cmdBuffer;
|
||||||
|
VK_CHECK_RESULT(vkAllocateCommandBuffers(m_logicalDevice, &cmdBufAllocateInfo, &cmdBuffer));
|
||||||
|
|
||||||
|
// 开始记录指令buffer
|
||||||
|
if (begin) {
|
||||||
|
beginCommandBuffer(cmdBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmdBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanDevice::beginCommandBuffer(VkCommandBuffer commandBuffer)
|
||||||
|
{
|
||||||
|
VkCommandBufferBeginInfo commandBufferBI{};
|
||||||
|
commandBufferBI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
VK_CHECK_RESULT(vkBeginCommandBuffer(commandBuffer, &commandBufferBI));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanDevice::flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, bool free = true)
|
||||||
|
{
|
||||||
|
VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer));
|
||||||
|
|
||||||
|
VkSubmitInfo submitInfo{};
|
||||||
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &commandBuffer;
|
||||||
|
|
||||||
|
//创建同步栅栏,确保命令buffer执行完毕
|
||||||
|
VkFenceCreateInfo fenceInfo{};
|
||||||
|
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
|
VkFence fence;
|
||||||
|
VK_CHECK_RESULT(vkCreateFence(m_logicalDevice, &fenceInfo, nullptr, &fence));
|
||||||
|
|
||||||
|
// 提交队列
|
||||||
|
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence));
|
||||||
|
// 等待栅栏发出信号说明命令buffer执行完毕
|
||||||
|
VK_CHECK_RESULT(vkWaitForFences(m_logicalDevice, 1, &fence, VK_TRUE, 100000000000));
|
||||||
|
// 同步栅栏使命结束,销毁
|
||||||
|
vkDestroyFence(m_logicalDevice, fence, nullptr);
|
||||||
|
// 需要的时候,销毁命令buffer
|
||||||
|
if (free) {
|
||||||
|
vkFreeCommandBuffers(m_logicalDevice, m_commandPool, 1, &commandBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VULKANBASE_NAMESPACE_END
|
|
@ -0,0 +1,97 @@
|
||||||
|
#ifndef VULKANDEVICE_H
|
||||||
|
#define VULKANDEVICE_H
|
||||||
|
|
||||||
|
#include "VulkanBase_Common.h"
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
VULKANBASE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/// @brief vulkan的设备类
|
||||||
|
class VulkanDevice
|
||||||
|
{
|
||||||
|
/// @brief 构造和setter/getter
|
||||||
|
public:
|
||||||
|
VulkanDevice();
|
||||||
|
VulkanDevice(VkPhysicalDevice physicalDevice);
|
||||||
|
~VulkanDevice();
|
||||||
|
|
||||||
|
VkDevice getLogicalDevice();
|
||||||
|
VkPhysicalDevice getPhysicalDevice();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// @brief 获取已设置所有请求属性位的设备内存类型的索引
|
||||||
|
/// @param typeBits 请求的每种设备内存类型设置的位掩码,通常通过VkMemoryRequirements获取
|
||||||
|
/// @param properties 要请求的设备内存类型的属性位掩码
|
||||||
|
/// @param memTypeFound 如果符合的设备内存类型存在,则该指针的布尔值为true
|
||||||
|
/// @return 请求的设备内存类型的索引
|
||||||
|
/// @throw 如果 memTypeFound 为空且找不到支持需要的属性的设备内存类型,则抛出异常
|
||||||
|
uint32_t getMemoryType(uint32_t typeBits, VkMemoryPropertyFlags properties, VkBool32* memTypeFound = nullptr);
|
||||||
|
/// @brief 获取支持所请求队列标志的队列族的索引
|
||||||
|
/// @param queueFlags 用于查找队列族索引的队列标志
|
||||||
|
/// @return 与标志匹配的队列族索引
|
||||||
|
/// @throw 如果找不到支持所请求标志的队列族索引,则抛出异常
|
||||||
|
uint32_t getQueueFamilyIndex(VkQueueFlagBits queueFlags);
|
||||||
|
/// @brief 据分配的物理设备创建逻辑设备,同时获取默认队列族索引
|
||||||
|
/// @param enabledFeatures 在创建设备时启用某些功能
|
||||||
|
/// @param enabledExtensions 在创建设备时启用某些扩展
|
||||||
|
/// @param requestedQueueTypes 指定要从设备请求的队列类型
|
||||||
|
/// @return 逻辑设备是否成功创建
|
||||||
|
VkResult createLogicalDevice(VkPhysicalDeviceFeatures enabledFeatures, std::vector<const char*> enabledExtensions, VkQueueFlags requestedQueueTypes = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
|
||||||
|
/// @brief 在设备上创建缓冲区
|
||||||
|
/// @param usageFlags 缓冲区的使用标志位掩码(即索引、顶点、统一缓冲区)
|
||||||
|
/// @param memoryPropertyFlags 此缓冲区的内存属性(即设备本地、主机可见、一致)
|
||||||
|
/// @param size 缓冲区的大小(以字节为单位)
|
||||||
|
/// @param buffer 指向函数获取的缓冲区句柄的指针
|
||||||
|
/// @param memory 指向函数获取的设备内存句柄的指针
|
||||||
|
/// @param data 指向创建后应复制到缓冲区的数据的指针(可选,如果未设置,则不会复制任何数据)
|
||||||
|
/// @return 如果已创建缓冲区句柄和设备内存并且已复制数据(可选传递),则返回 VK_SUCCESS
|
||||||
|
VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, VkBuffer* buffer, VkDeviceMemory* memory, void* data = nullptr);
|
||||||
|
/// @brief 创建命令池以分配命令缓冲区
|
||||||
|
/// @param queueFamilyIndex 要为其创建命令池的队列的系列索引
|
||||||
|
/// @param createFlags 可选)命令池创建标志(默认为 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
|
||||||
|
/// @return 创建的命令缓冲区的句柄
|
||||||
|
VkCommandPool createCommandPool(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
||||||
|
/// @brief 从命令池中分配命令缓冲区
|
||||||
|
/// @param level 新命令缓冲区的级别(主或次)
|
||||||
|
/// @param begin 为 true时开始在新命令缓冲区上进行记录
|
||||||
|
/// @return 分配的命令缓冲区的句柄
|
||||||
|
VkCommandBuffer createCommandBuffer(VkCommandBufferLevel level, bool begin = false);
|
||||||
|
/// @brief 开始在指定命令缓冲区记录
|
||||||
|
/// @param commandBuffer
|
||||||
|
void beginCommandBuffer(VkCommandBuffer commandBuffer);
|
||||||
|
/// @brief 停止指定命令缓冲区记录并将其提交到队列,使用栅栏来确保命令缓冲区已完成执行
|
||||||
|
/// @param commandBuffer 要刷新的命令缓冲区
|
||||||
|
/// @param queue 要将命令缓冲区提交到的队列
|
||||||
|
/// @param free 提交后释放命令缓冲区(默认为 true)
|
||||||
|
void flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, bool free = true);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
VkPhysicalDevice m_physicalDevice;
|
||||||
|
VkDevice m_logicalDevice;
|
||||||
|
VkPhysicalDeviceProperties m_properties;
|
||||||
|
VkPhysicalDeviceFeatures m_features;
|
||||||
|
VkPhysicalDeviceFeatures m_enabledFeatures;
|
||||||
|
VkPhysicalDeviceMemoryProperties m_memoryProperties;
|
||||||
|
std::vector<VkQueueFamilyProperties> m_queueFamilyProperties;
|
||||||
|
VkCommandPool m_commandPool;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint32_t graphics;
|
||||||
|
uint32_t compute;
|
||||||
|
} m_queueFamilyIndices;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VULKANBASE_NAMESPACE_END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !VULKANDEVICE_H
|
|
@ -0,0 +1,68 @@
|
||||||
|
#include "VulkanTextureSampler.h"
|
||||||
|
|
||||||
|
VULKANBASE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
VulkanTextureSampler::VulkanTextureSampler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanTextureSampler::~VulkanTextureSampler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFilter VulkanTextureSampler::getMaxFilter()
|
||||||
|
{
|
||||||
|
return m_maxFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanTextureSampler::setMaxFilter(VkFilter maxFilter)
|
||||||
|
{
|
||||||
|
m_maxFilter = maxFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFilter VulkanTextureSampler::getMinFilter()
|
||||||
|
{
|
||||||
|
return m_minFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanTextureSampler::setMinFilter(VkFilter minFilter)
|
||||||
|
{
|
||||||
|
m_minFilter = minFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSamplerAddressMode VulkanTextureSampler::getAddressModeU()
|
||||||
|
{
|
||||||
|
return m_addressModeU;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanTextureSampler::setAddressModeU(VkSamplerAddressMode samplerAddresMode)
|
||||||
|
{
|
||||||
|
m_addressModeU = samplerAddresMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSamplerAddressMode VulkanTextureSampler::getAddressModeV()
|
||||||
|
{
|
||||||
|
return m_addressModeV;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanTextureSampler::setAddressModeV(VkSamplerAddressMode samplerAddresMode)
|
||||||
|
{
|
||||||
|
m_addressModeV = samplerAddresMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSamplerAddressMode VulkanTextureSampler::getAddressModeW()
|
||||||
|
{
|
||||||
|
return m_addressModeW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanTextureSampler::setAddressModeW(VkSamplerAddressMode samplerAddresMode)
|
||||||
|
{
|
||||||
|
m_addressModeW = samplerAddresMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VULKANBASE_NAMESPACE_END
|
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef VULKANTEXTURESAMPLER_H
|
||||||
|
#define VULKANTEXTURESAMPLER_H
|
||||||
|
|
||||||
|
#include "VulkanBase_Common.h"
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
VULKANBASE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
||||||
|
/// @brief 贴图采样器,暂时适用于gltf模型贴图
|
||||||
|
class VulkanTextureSampler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VulkanTextureSampler();
|
||||||
|
~VulkanTextureSampler();
|
||||||
|
|
||||||
|
VkFilter getMaxFilter();
|
||||||
|
void setMaxFilter(VkFilter maxFilter);
|
||||||
|
|
||||||
|
VkFilter getMinFilter();
|
||||||
|
void setMinFilter(VkFilter minFilter);
|
||||||
|
|
||||||
|
VkSamplerAddressMode getAddressModeU();
|
||||||
|
void setAddressModeU(VkSamplerAddressMode samplerAddresMode);
|
||||||
|
|
||||||
|
VkSamplerAddressMode getAddressModeV();
|
||||||
|
void setAddressModeV(VkSamplerAddressMode samplerAddresMode);
|
||||||
|
|
||||||
|
VkSamplerAddressMode getAddressModeW();
|
||||||
|
void setAddressModeW(VkSamplerAddressMode samplerAddresMode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
VkFilter m_maxFilter;
|
||||||
|
VkFilter m_minFilter;
|
||||||
|
VkSamplerAddressMode m_addressModeU;
|
||||||
|
VkSamplerAddressMode m_addressModeV;
|
||||||
|
VkSamplerAddressMode m_addressModeW;
|
||||||
|
};
|
||||||
|
|
||||||
|
VULKANBASE_NAMESPACE_END
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !VULKANTEXTURESAMPLER_H
|
|
@ -1,4 +1,4 @@
|
||||||
#include "glTFBoundingBox.h"
|
#include "glTFBoundingBox.h"
|
||||||
|
|
||||||
GLTFLOADER_NAMESPACE_BEGIN
|
GLTFLOADER_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,270 @@
|
||||||
|
#include "glTFTexture.h"
|
||||||
|
#include <VulkanTools.h>
|
||||||
|
|
||||||
|
GLTFLOADER_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
glTFTexture::glTFTexture()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
glTFTexture::~glTFTexture()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void glTFTexture::updateDescriptor()
|
||||||
|
{
|
||||||
|
m_descriptor.sampler = m_sampler;
|
||||||
|
m_descriptor.imageView = m_view;
|
||||||
|
m_descriptor.imageLayout = m_imageLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void glTFTexture::destroy()
|
||||||
|
{
|
||||||
|
VkDevice logicalDevice = m_device->getLogicalDevice();
|
||||||
|
vkDestroyImageView(logicalDevice, m_view, nullptr);
|
||||||
|
vkDestroyImage(logicalDevice, m_image, nullptr);
|
||||||
|
vkFreeMemory(logicalDevice, m_deviceMemory, nullptr);
|
||||||
|
vkDestroySampler(logicalDevice, m_sampler, nullptr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void glTFTexture::fromglTfImage(tinygltf::Image& gltfimage, VulkanBase::VulkanTextureSampler textureSampler, VulkanBase::VulkanDevice* device, VkQueue copyQueue)
|
||||||
|
{
|
||||||
|
VkDevice logicalDevice = device->getLogicalDevice();
|
||||||
|
unsigned char* buffer = nullptr;
|
||||||
|
VkDeviceSize bufferSize = 0;
|
||||||
|
bool deleteBuffer = false;
|
||||||
|
if (gltfimage.component == 3) {
|
||||||
|
/// 即使创建为24bit的rgb,硬件上依旧是rgba,因此填充alpha值,但带宽压力上升25%
|
||||||
|
/// 可选todo:采用计算着色器将rgb写入uniform buffer
|
||||||
|
bufferSize = gltfimage.width * gltfimage.height * 4;
|
||||||
|
buffer = new unsigned char[bufferSize];
|
||||||
|
unsigned char* rgba = buffer;
|
||||||
|
unsigned char* rgb = &gltfimage.image[0];
|
||||||
|
for (int32_t i = 0; i < gltfimage.width * gltfimage.height; ++i) {
|
||||||
|
for (int32_t j = 0; j < 3; ++j) {
|
||||||
|
rgba[j] = rgb[j];
|
||||||
|
}
|
||||||
|
rgba += 4;
|
||||||
|
rgb += 3;
|
||||||
|
}
|
||||||
|
deleteBuffer = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buffer = &gltfimage.image[0];
|
||||||
|
bufferSize = gltfimage.image.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
|
||||||
|
VkFormatProperties formatProperties;
|
||||||
|
|
||||||
|
m_width = gltfimage.width;
|
||||||
|
m_height = gltfimage.height;
|
||||||
|
m_mipLevels = static_cast<uint32_t>(floor(log2(std::max(m_width, m_height))) + 1.0);
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceFormatProperties(device->getPhysicalDevice(), format, &formatProperties);
|
||||||
|
assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT);
|
||||||
|
assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT);
|
||||||
|
/// 分配存放缓冲区的设备内存
|
||||||
|
VkMemoryAllocateInfo memAllocInfo{};
|
||||||
|
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
VkMemoryRequirements memReqs{};
|
||||||
|
|
||||||
|
VkBuffer stagingBuffer;
|
||||||
|
VkDeviceMemory stagingMemory;
|
||||||
|
|
||||||
|
VkBufferCreateInfo bufferCreateInfo{};
|
||||||
|
bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
bufferCreateInfo.size = bufferSize;
|
||||||
|
bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||||
|
bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
VK_CHECK_RESULT(vkCreateBuffer(logicalDevice, &bufferCreateInfo, nullptr, &stagingBuffer));
|
||||||
|
vkGetBufferMemoryRequirements(logicalDevice, stagingBuffer, &memReqs);
|
||||||
|
memAllocInfo.allocationSize = memReqs.size;
|
||||||
|
memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
|
VK_CHECK_RESULT(vkAllocateMemory(logicalDevice, &memAllocInfo, nullptr, &stagingMemory));
|
||||||
|
VK_CHECK_RESULT(vkBindBufferMemory(logicalDevice, stagingBuffer, stagingMemory, 0));
|
||||||
|
// 向设备内存中写入缓冲区
|
||||||
|
uint8_t* data;
|
||||||
|
VK_CHECK_RESULT(vkMapMemory(logicalDevice, stagingMemory, 0, memReqs.size, 0, (void**)&data));
|
||||||
|
memcpy(data, buffer, bufferSize);
|
||||||
|
vkUnmapMemory(logicalDevice, stagingMemory);
|
||||||
|
/// 创建图片类型设备内存
|
||||||
|
VkImageCreateInfo imageCreateInfo{};
|
||||||
|
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
|
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||||
|
imageCreateInfo.format = format;
|
||||||
|
imageCreateInfo.mipLevels = m_mipLevels;
|
||||||
|
imageCreateInfo.arrayLayers = 1;
|
||||||
|
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
imageCreateInfo.extent = { m_width, m_height, 1 };
|
||||||
|
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
VK_CHECK_RESULT(vkCreateImage(logicalDevice, &imageCreateInfo, nullptr, &m_image));
|
||||||
|
vkGetImageMemoryRequirements(logicalDevice, m_image, &memReqs);
|
||||||
|
memAllocInfo.allocationSize = memReqs.size;
|
||||||
|
memAllocInfo.memoryTypeIndex = device->getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
VK_CHECK_RESULT(vkAllocateMemory(logicalDevice, &memAllocInfo, nullptr, &m_deviceMemory));
|
||||||
|
VK_CHECK_RESULT(vkBindImageMemory(logicalDevice, m_image, m_deviceMemory, 0));
|
||||||
|
/// 分配复制命令缓冲区
|
||||||
|
VkCommandBuffer copyCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||||
|
|
||||||
|
VkImageSubresourceRange subresourceRange = {};
|
||||||
|
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
subresourceRange.levelCount = 1;
|
||||||
|
subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
{
|
||||||
|
/// 插入barrier,强制管线等待上方指令完成
|
||||||
|
VkImageMemoryBarrier imageMemoryBarrier{};
|
||||||
|
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
|
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
imageMemoryBarrier.srcAccessMask = 0;
|
||||||
|
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
imageMemoryBarrier.image = m_image;
|
||||||
|
imageMemoryBarrier.subresourceRange = subresourceRange;
|
||||||
|
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkBufferImageCopy bufferCopyRegion = {};
|
||||||
|
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
bufferCopyRegion.imageSubresource.mipLevel = 0;
|
||||||
|
bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
|
||||||
|
bufferCopyRegion.imageSubresource.layerCount = 1;
|
||||||
|
bufferCopyRegion.imageExtent.width = m_width;
|
||||||
|
bufferCopyRegion.imageExtent.height = m_height;
|
||||||
|
bufferCopyRegion.imageExtent.depth = 1;
|
||||||
|
|
||||||
|
vkCmdCopyBufferToImage(copyCmd, stagingBuffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
|
||||||
|
|
||||||
|
{
|
||||||
|
/// 插入barrier,管线等待copy操作完成
|
||||||
|
VkImageMemoryBarrier imageMemoryBarrier{};
|
||||||
|
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
|
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
|
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
imageMemoryBarrier.image = m_image;
|
||||||
|
imageMemoryBarrier.subresourceRange = subresourceRange;
|
||||||
|
vkCmdPipelineBarrier(copyCmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
|
||||||
|
}
|
||||||
|
/// 提交到命令队列
|
||||||
|
device->flushCommandBuffer(copyCmd, copyQueue, true);
|
||||||
|
/// 销毁图片buffer存储的设备内存
|
||||||
|
vkFreeMemory(logicalDevice, stagingMemory, nullptr);
|
||||||
|
/// 销毁图片buffer存储的设备缓冲区
|
||||||
|
vkDestroyBuffer(logicalDevice, stagingBuffer, nullptr);
|
||||||
|
|
||||||
|
// 生成mip-map链 (glTF 使用 jpg 和 png 格式, 需要当场生成mip-map)
|
||||||
|
VkCommandBuffer blitCmd = device->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||||
|
for (uint32_t i = 1; i < m_mipLevels; i++) {
|
||||||
|
VkImageBlit imageBlit{};
|
||||||
|
|
||||||
|
imageBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
imageBlit.srcSubresource.layerCount = 1;
|
||||||
|
imageBlit.srcSubresource.mipLevel = i - 1;
|
||||||
|
imageBlit.srcOffsets[1].x = int32_t(m_width >> (i - 1));
|
||||||
|
imageBlit.srcOffsets[1].y = int32_t(m_height >> (i - 1));
|
||||||
|
imageBlit.srcOffsets[1].z = 1;
|
||||||
|
|
||||||
|
imageBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
imageBlit.dstSubresource.layerCount = 1;
|
||||||
|
imageBlit.dstSubresource.mipLevel = i;
|
||||||
|
imageBlit.dstOffsets[1].x = int32_t(m_width >> i);
|
||||||
|
imageBlit.dstOffsets[1].y = int32_t(m_height >> i);
|
||||||
|
imageBlit.dstOffsets[1].z = 1;
|
||||||
|
|
||||||
|
VkImageSubresourceRange mipSubRange = {};
|
||||||
|
mipSubRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
mipSubRange.baseMipLevel = i;
|
||||||
|
mipSubRange.levelCount = 1;
|
||||||
|
mipSubRange.layerCount = 1;
|
||||||
|
|
||||||
|
{
|
||||||
|
VkImageMemoryBarrier imageMemoryBarrier{};
|
||||||
|
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
|
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
imageMemoryBarrier.srcAccessMask = 0;
|
||||||
|
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
imageMemoryBarrier.image = m_image;
|
||||||
|
imageMemoryBarrier.subresourceRange = mipSubRange;
|
||||||
|
vkCmdPipelineBarrier(blitCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
vkCmdBlitImage(blitCmd, m_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_LINEAR);
|
||||||
|
|
||||||
|
{
|
||||||
|
VkImageMemoryBarrier imageMemoryBarrier{};
|
||||||
|
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
|
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
|
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
imageMemoryBarrier.image = m_image;
|
||||||
|
imageMemoryBarrier.subresourceRange = mipSubRange;
|
||||||
|
vkCmdPipelineBarrier(blitCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subresourceRange.levelCount = m_mipLevels;
|
||||||
|
m_imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
|
{
|
||||||
|
VkImageMemoryBarrier imageMemoryBarrier{};
|
||||||
|
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||||
|
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||||
|
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
|
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
|
imageMemoryBarrier.image = m_image;
|
||||||
|
imageMemoryBarrier.subresourceRange = subresourceRange;
|
||||||
|
vkCmdPipelineBarrier(blitCmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_device->flushCommandBuffer(blitCmd, copyQueue, true);
|
||||||
|
|
||||||
|
/// 创建贴图采样器
|
||||||
|
VkSamplerCreateInfo samplerInfo{};
|
||||||
|
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||||
|
samplerInfo.magFilter = textureSampler.getMaxFilter();
|
||||||
|
samplerInfo.minFilter = textureSampler.getMinFilter();
|
||||||
|
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||||
|
samplerInfo.addressModeU = textureSampler.getAddressModeU();
|
||||||
|
samplerInfo.addressModeV = textureSampler.getAddressModeV();
|
||||||
|
samplerInfo.addressModeW = textureSampler.getAddressModeW();
|
||||||
|
samplerInfo.compareOp = VK_COMPARE_OP_NEVER;
|
||||||
|
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||||
|
samplerInfo.maxAnisotropy = 1.0;
|
||||||
|
samplerInfo.anisotropyEnable = VK_FALSE;
|
||||||
|
samplerInfo.maxLod = (float)m_mipLevels;
|
||||||
|
samplerInfo.maxAnisotropy = 8.0f;
|
||||||
|
samplerInfo.anisotropyEnable = VK_TRUE;
|
||||||
|
VK_CHECK_RESULT(vkCreateSampler(logicalDevice, &samplerInfo, nullptr, &m_sampler));
|
||||||
|
|
||||||
|
/// 创建图片的数据视图,用于读写图片
|
||||||
|
VkImageViewCreateInfo viewInfo{};
|
||||||
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
viewInfo.image = m_image;
|
||||||
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
viewInfo.format = format;
|
||||||
|
viewInfo.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
|
||||||
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
|
viewInfo.subresourceRange.levelCount = m_mipLevels;
|
||||||
|
VK_CHECK_RESULT(vkCreateImageView(logicalDevice, &viewInfo, nullptr, &m_view));
|
||||||
|
|
||||||
|
updateDescriptor();
|
||||||
|
|
||||||
|
if (deleteBuffer)
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GLTFLOADER_NAMESPACE_END
|
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef GLTFTEXTURE_H
|
||||||
|
#define GLTFTEXTURE_H
|
||||||
|
|
||||||
|
#include "glTFModel_Common.h"
|
||||||
|
|
||||||
|
#include "VulkanDevice.h"
|
||||||
|
#include "VulkanTextureSampler.h"
|
||||||
|
|
||||||
|
#include <tiny_gltf.h>
|
||||||
|
|
||||||
|
|
||||||
|
GLTFLOADER_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
/// @brief gltf模型的贴图
|
||||||
|
class GLTFLOADER_API glTFTexture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
glTFTexture();
|
||||||
|
~glTFTexture();
|
||||||
|
|
||||||
|
void updateDescriptor();
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
void fromglTfImage(tinygltf::Image& gltfimage, VulkanBase::VulkanTextureSampler textureSampler, VulkanBase::VulkanDevice* device, VkQueue copyQueue);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
VulkanBase::VulkanDevice* m_device;
|
||||||
|
VkImage m_image;
|
||||||
|
VkImageLayout m_imageLayout;
|
||||||
|
VkDeviceMemory m_deviceMemory;
|
||||||
|
VkImageView m_view;
|
||||||
|
uint32_t m_width, m_height;
|
||||||
|
uint32_t m_mipLevels;
|
||||||
|
uint32_t m_layerCount;
|
||||||
|
VkDescriptorImageInfo m_descriptor;
|
||||||
|
VkSampler m_sampler;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLTFLOADER_NAMESPACE_END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !GLTFTEXTURE_H
|
Loading…
Reference in New Issue