2019-05-18 15:41:49 +08:00
|
|
|
|
#include<hgl/graph/vulkan/VKTexture.h>
|
2019-05-18 16:10:42 +08:00
|
|
|
|
#include<hgl/graph/vulkan/VKSampler.h>
|
2019-05-18 15:41:49 +08:00
|
|
|
|
#include<hgl/graph/vulkan/VKDevice.h>
|
|
|
|
|
#include<hgl/graph/vulkan/VKPhysicalDevice.h>
|
|
|
|
|
#include<hgl/graph/vulkan/VKBuffer.h>
|
|
|
|
|
#include<hgl/graph/vulkan/VKCommandBuffer.h>
|
|
|
|
|
VK_NAMESPACE_BEGIN
|
|
|
|
|
namespace
|
|
|
|
|
{
|
|
|
|
|
uint32_t GetMipLevels(uint32_t size)
|
|
|
|
|
{
|
|
|
|
|
uint32_t level=1;
|
|
|
|
|
|
|
|
|
|
while(size>>=1)
|
|
|
|
|
++level;
|
|
|
|
|
|
|
|
|
|
return level;
|
|
|
|
|
}
|
|
|
|
|
}//namespace
|
|
|
|
|
|
|
|
|
|
Texture2D *Device::CreateTexture2D(const VkFormat video_format,void *data,uint32_t width,uint32_t height,uint32_t size,bool force_linear)
|
|
|
|
|
{
|
|
|
|
|
if(!data||width<=1||height<=1)return(nullptr);
|
|
|
|
|
|
2019-05-19 13:02:35 +08:00
|
|
|
|
const VkFormatProperties fp=attr->physical_device->GetFormatProperties(video_format);
|
2019-05-18 15:41:49 +08:00
|
|
|
|
|
2019-05-19 13:02:35 +08:00
|
|
|
|
if(fp.optimalTilingFeatures&VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)
|
|
|
|
|
{
|
|
|
|
|
if(force_linear)
|
|
|
|
|
{
|
|
|
|
|
if(!(fp.linearTilingFeatures&VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
|
|
|
|
|
force_linear=false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else //不能用优化存储,这种现像好像不存在啊
|
|
|
|
|
{
|
|
|
|
|
if(!(fp.linearTilingFeatures&VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
|
|
|
|
|
{
|
|
|
|
|
//也不能用线性储存??WTF ?
|
|
|
|
|
return(nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
force_linear=true;
|
|
|
|
|
return(nullptr); //这个我们暂时不支持
|
2019-05-18 15:41:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TextureData *tex_data=new TextureData();
|
|
|
|
|
|
|
|
|
|
tex_data->image=nullptr;
|
|
|
|
|
tex_data->image_view=nullptr;
|
|
|
|
|
|
|
|
|
|
tex_data->mip_levels=1;
|
|
|
|
|
tex_data->linear=false;
|
|
|
|
|
|
|
|
|
|
if(force_linear)
|
|
|
|
|
{
|
|
|
|
|
delete tex_data;
|
|
|
|
|
return(nullptr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#define VK_CHECK_RESULT(func) if(func!=VK_SUCCESS){delete tex_data;return(nullptr);}
|
|
|
|
|
|
|
|
|
|
Buffer *buf=CreateBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT,size,data);
|
|
|
|
|
|
2019-05-19 13:02:35 +08:00
|
|
|
|
VkBufferImageCopy buffer_image_copy{};
|
2019-05-18 15:41:49 +08:00
|
|
|
|
buffer_image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
buffer_image_copy.imageSubresource.mipLevel = 0;
|
|
|
|
|
buffer_image_copy.imageSubresource.baseArrayLayer = 0;
|
|
|
|
|
buffer_image_copy.imageSubresource.layerCount = 1;
|
|
|
|
|
buffer_image_copy.imageExtent.width = width;
|
|
|
|
|
buffer_image_copy.imageExtent.height = height;
|
|
|
|
|
buffer_image_copy.imageExtent.depth = 1;
|
|
|
|
|
buffer_image_copy.bufferOffset = 0;
|
|
|
|
|
|
|
|
|
|
tex_data->image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
|
|
|
|
|
|
|
|
VkDeviceMemory device_memory;
|
|
|
|
|
|
2019-05-19 13:02:35 +08:00
|
|
|
|
VkImageCreateInfo imageCreateInfo{};
|
2019-05-18 15:41:49 +08:00
|
|
|
|
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
|
|
|
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
|
|
|
|
imageCreateInfo.format = video_format;
|
|
|
|
|
imageCreateInfo.mipLevels = 1;
|
|
|
|
|
imageCreateInfo.arrayLayers = 1;
|
|
|
|
|
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
|
|
|
imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
|
|
|
// Set initial layout of the image to undefined
|
|
|
|
|
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
|
imageCreateInfo.extent = { width, height, 1 };
|
|
|
|
|
imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
|
|
|
|
|
VK_CHECK_RESULT(vkCreateImage(attr->device, &imageCreateInfo, nullptr, &tex_data->image))
|
|
|
|
|
|
2019-05-19 13:02:35 +08:00
|
|
|
|
VkMemoryAllocateInfo memAllocInfo{};
|
|
|
|
|
VkMemoryRequirements memReqs{};
|
2019-05-18 15:41:49 +08:00
|
|
|
|
|
|
|
|
|
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
|
|
|
|
|
|
|
|
vkGetImageMemoryRequirements(attr->device, tex_data->image, &memReqs);
|
|
|
|
|
memAllocInfo.allocationSize = memReqs.size;
|
|
|
|
|
attr->CheckMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,&memAllocInfo.memoryTypeIndex);
|
|
|
|
|
VK_CHECK_RESULT(vkAllocateMemory(attr->device, &memAllocInfo, nullptr, &device_memory))
|
|
|
|
|
VK_CHECK_RESULT(vkBindImageMemory(attr->device, tex_data->image, device_memory, 0))
|
|
|
|
|
|
|
|
|
|
CommandBuffer *cmd_buf=CreateCommandBuffer();
|
|
|
|
|
|
|
|
|
|
VkImageSubresourceRange subresourceRange = {};
|
|
|
|
|
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
subresourceRange.baseMipLevel = 0;
|
|
|
|
|
subresourceRange.levelCount = 1;
|
|
|
|
|
subresourceRange.layerCount = 1;
|
|
|
|
|
|
2019-05-19 13:02:35 +08:00
|
|
|
|
VkImageMemoryBarrier imageMemoryBarrier{};
|
2019-05-18 15:41:49 +08:00
|
|
|
|
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
|
|
|
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
|
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
|
|
imageMemoryBarrier.image = tex_data->image;
|
|
|
|
|
imageMemoryBarrier.subresourceRange = subresourceRange;
|
|
|
|
|
imageMemoryBarrier.srcAccessMask = 0;
|
|
|
|
|
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
|
|
|
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
|
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
|
|
|
|
|
|
|
|
cmd_buf->Begin();
|
|
|
|
|
cmd_buf->PipelineBarrier(
|
|
|
|
|
VK_PIPELINE_STAGE_HOST_BIT,
|
|
|
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
|
|
|
0,
|
|
|
|
|
0, nullptr,
|
|
|
|
|
0, nullptr,
|
|
|
|
|
1, &imageMemoryBarrier);
|
|
|
|
|
|
|
|
|
|
cmd_buf->CopyBufferToImage(
|
|
|
|
|
*buf,
|
|
|
|
|
tex_data->image,
|
|
|
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
|
|
|
|
1,
|
|
|
|
|
&buffer_image_copy);
|
|
|
|
|
|
|
|
|
|
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
|
|
|
|
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
|
|
|
imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
|
|
|
|
imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
|
|
|
|
|
|
|
|
cmd_buf->PipelineBarrier(
|
|
|
|
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
|
|
|
|
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
|
|
|
|
|
0,
|
|
|
|
|
0, nullptr,
|
|
|
|
|
0, nullptr,
|
|
|
|
|
1, &imageMemoryBarrier);
|
|
|
|
|
|
|
|
|
|
cmd_buf->End();
|
|
|
|
|
QueueSubmit(*cmd_buf);
|
|
|
|
|
Wait();
|
|
|
|
|
delete buf;
|
|
|
|
|
|
|
|
|
|
tex_data->image_view=CreateImageView2D(attr->device,video_format,VK_IMAGE_ASPECT_COLOR_BIT,tex_data->image);
|
|
|
|
|
|
|
|
|
|
#undef VK_CHECK_RESULT
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-18 16:10:42 +08:00
|
|
|
|
return(new Texture2D(width,height,attr->device,tex_data));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Sampler *Device::CreateSampler(VkSamplerCreateInfo *sci)
|
|
|
|
|
{
|
|
|
|
|
if(!sci)return(nullptr);
|
|
|
|
|
|
|
|
|
|
VkSampler sampler;
|
|
|
|
|
|
|
|
|
|
if(attr->physical_device->features.samplerAnisotropy)
|
|
|
|
|
{
|
|
|
|
|
sci->maxAnisotropy = attr->physical_device->properties.limits.maxSamplerAnisotropy;
|
|
|
|
|
sci->anisotropyEnable = VK_TRUE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sci->maxAnisotropy = 1.0;
|
|
|
|
|
sci->anisotropyEnable = VK_FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(vkCreateSampler(attr->device,sci,nullptr,&sampler)!=VK_SUCCESS)
|
|
|
|
|
return(nullptr);
|
|
|
|
|
|
|
|
|
|
return(new Sampler(attr->device,sampler));
|
2019-05-18 15:41:49 +08:00
|
|
|
|
}
|
|
|
|
|
VK_NAMESPACE_END
|