Workaround clang bugs, add separate header with handy constructor wrappers, use vulkan generated wrappers

This commit is contained in:
mittorn 2024-10-16 10:10:47 +03:00
parent 91ff840a78
commit 5b80993b28
4 changed files with 164 additions and 125 deletions

View file

@ -23,21 +23,17 @@
*/
#ifndef POSITIONAL_UTL_H
#define POSITIONAL_UTL_H
// wrapper for chains with pNext
template <typename T, typename... Ts>
struct StructureChain : T, StructureChain<Ts...>
{
StructureChain(const T &t, const Ts&... a) : T(t), StructureChain<Ts...>(a...)
{
((T*)this)->pNext = (StructureChain<Ts...>*)this;
}
};
template <typename T>
struct StructureChain<T> : T
{
StructureChain(const T &t) : T(t){}
};
struct ClearType_w{ typedef T tp; };
template <typename T>
struct ClearType_w<T&> { typedef T tp; };
template <class T>
struct ClearType_w<T&&> { typedef T tp; };
template <class T>
struct ClearType_w<const T&> { typedef T tp; };
#define ClearType(x) ClearType_w<x>::tp
#define ClearValType(x) typename ClearType_w<decltype(x)>::tp
// Positional arguments? Im my C++? It's more likely than you think!
enum SetterOperation
@ -225,43 +221,39 @@ template <typename T, typename... Ts>
void $F(T &t, const Ts&... ts) // fills all SetterVal's member pointers with it's values
{
auto filler = [](T &t, const auto &arg){
if constexpr(arg.op == AssignArrayPtrWithLength)
// broken clang constexpr fails on arg.op!!!
constexpr SetterOperation op = ClearType(decltype(arg))::op;
if constexpr(op == AssignArrayPtrWithLength)
{
t.*arg.arr.member.func(Twrap<T>{}) = arg.val.array;
t.*arg.arr.count.func(Twrap<T>{}) = arg.val.count;
}
else if constexpr(arg.op == AssignArrayCopyWithLength)
else if constexpr(op == AssignArrayCopyWithLength)
{
for(int i = 0; i < arg.val.count; i++)
(t.*arg.member.func(Twrap<T>{}))[i] = arg.val.array[i];
t.*arg.arr.count.func(Twrap<T>{}) = arg.val.count;
}
else if constexpr(arg.op == AssignArrayByIndex)
else if constexpr(op == AssignArrayByIndex)
(t.*arg.arr.member.func(Twrap<T>{}))[arg.arr.idx] = arg.val;
else if constexpr(arg.op == AssignArrayCopy)
else if constexpr(op == AssignArrayCopy)
for(int i = 0; i < arg.val.count; i++)
(t.*arg.member.func(Twrap<T>{}))[i] = arg.val.array[i];
else if constexpr(arg.op == CallMethod)
else if constexpr(op == CallMethod)
arg.vals.CallMember(arg.func.func(Twrap<T>{}), t);
else if constexpr(arg.op == UpdateObject)
else if constexpr(op == UpdateObject)
arg.val(t.*arg.member.func(Twrap<T>{}));
else if constexpr(arg.op == AssignObject)
else if constexpr(op == AssignObject)
{
t.*arg.member.func(Twrap<T>{}) = {};
arg.val(t.*arg.member.func(Twrap<T>{}));
}
else if constexpr(arg.op == AppendObject)
else if constexpr(op == AppendObject)
t.*arg.member.func(Twrap<T>{}) += arg.val;
else if constexpr(arg.op == SetTrue)
{
auto v = t.*arg.func(Twrap<T>{});
t.*arg.func(Twrap<T>{}) = (decltype(v))1;
}
else if constexpr(op == SetTrue)
t.*arg.func(Twrap<T>{}) = (ClearValType(t.*arg.func(Twrap<T>{})))(1);
else
{
auto v = t.*arg.member.func(Twrap<T>{});
t.*arg.member.func(Twrap<T>{}) = (decltype(v))(arg.val);
}
t.*arg.member.func(Twrap<T>{}) = (ClearValType(t.*arg.member.func(Twrap<T>{})))(arg.val);
};
(filler(t,ts),...);
}

View file

@ -25,6 +25,7 @@
#include "vulkan_pipeline_utl.h"
#include "vulkan_utl.h"
#include "vulkan_texture_utl.h"
#include "vulkan_contructors.h"
#include <string.h>
#include <math.h>
@ -103,50 +104,36 @@ struct ComputeApplication {
void ImportVaapiImage(VulkanTexture &texture0, VulkanTexture &texture1, int fd, uint64_t mod, uint32_t size, uint32_t offset, uint32_t pitch1, uint32_t pitch2, bool p010)
{
StructureChain layout{$M(VkSubresourceLayout{0},$(rowPitch) = pitch1)};
StructureChain iinfo{
$M(VkImageCreateInfo{VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO},
$(imageType) = VK_IMAGE_TYPE_2D,
$(format) = p010?VK_FORMAT_R16_UNORM:VK_FORMAT_R8_UNORM,
$(extent) = VkExtent3D{ WIDTH, HEIGHT, 1 },
$(mipLevels) = 1,
$(arrayLayers)= 1,
$(samples) =VK_SAMPLE_COUNT_1_BIT,
$(tiling) = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
$(usage) = VK_IMAGE_USAGE_STORAGE_BIT,
$(sharingMode) = VK_SHARING_MODE_EXCLUSIVE
),
$M(VkExternalMemoryImageCreateInfo{VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO},
$(handleTypes) = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
),
$M(VkImageDrmFormatModifierExplicitCreateInfoEXT{VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT},
$(drmFormatModifierPlaneCount) = 1,
$(drmFormatModifier) = mod,
$(pPlaneLayouts) &= layout
)
$Sc layout = SubresourceLayout(pitch1);
$Sc iinfo{Image2dInfo(
VK_IMAGE_USAGE_STORAGE_BIT,
p010?VK_FORMAT_R16_UNORM:VK_FORMAT_R8_UNORM,
WIDTH, HEIGHT,
$(tiling) = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT),
$Vk<VkExternalMemoryImageCreateInfo>(
$(handleTypes) = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT),
$Vk<VkImageDrmFormatModifierExplicitCreateInfoEXT>(
$(drmFormatModifierPlaneCount), $(drmFormatModifier) = mod,
$(pPlaneLayouts) &= layout)
};
VK_CHECK_RESULT(vkCreateImage(dev.device, &iinfo, NULL, &texture0.image)); // create image.
$F(iinfo,$(format) = p010?VK_FORMAT_R16G16_UNORM:VK_FORMAT_R8G8_UNORM, $(extent) = VkExtent3D{ WIDTH/2, HEIGHT/2, 1 });
$F(iinfo,$(format) = p010?VK_FORMAT_R16G16_UNORM:VK_FORMAT_R8G8_UNORM,
$(extent) = VkExtent3D{ WIDTH/2, HEIGHT/2, 1 });
$F(layout,$(offset) = 0, $(rowPitch) = pitch2 );
VK_CHECK_RESULT(vkCreateImage(dev.device, &iinfo, NULL, &texture1.image)); // create image.
VkMemoryRequirements memoryRequirements;
vkGetImageMemoryRequirements(dev.device, texture0.image, &memoryRequirements);
VkMemoryFdPropertiesKHR fdProps = {VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR};
VkMemoryFdPropertiesKHR fdProps = $Vk<VkMemoryFdPropertiesKHR>();
PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdProperties = (PFN_vkGetMemoryFdPropertiesKHR)vkGetInstanceProcAddr(context.instance, "vkGetMemoryFdPropertiesKHR");
vkGetMemoryFdProperties(dev.device,VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, fd, &fdProps);
StructureChain ainfo{
$M(VkMemoryAllocateInfo{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO},
$(allocationSize) = size //memoryRequirements.size; // specify required memory.
),
$M(VkImportMemoryFdInfoKHR{VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR},
$Sc ainfo{
AllocateInfo(size),
$Vk<VkImportMemoryFdInfoKHR>(
$(handleType) = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
$(fd) = fd
)
$(fd) = fd)
};
dev.GetMemoryType(memoryRequirements.memoryTypeBits & fdProps.memoryTypeBits, 0, &ainfo.memoryTypeIndex);//VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
@ -156,19 +143,11 @@ struct ComputeApplication {
VK_CHECK_RESULT(vkBindImageMemory(dev.device, texture0.image, texture0.device_memory, 0));
VK_CHECK_RESULT(vkBindImageMemory(dev.device, texture1.image, texture0.device_memory, offset));
$F(texture0,
$(image_layout) = VK_IMAGE_LAYOUT_UNDEFINED,
$(width) = WIDTH,
$(height) = HEIGHT,
$(mip_levels) = 1,
$(layer_count) = 1
);
$(width) = WIDTH, $(height) = HEIGHT,
$(mip_levels), $(layer_count));
$F(texture1,
$(image_layout) = VK_IMAGE_LAYOUT_UNDEFINED,
$(width) = WIDTH/2,
$(height) = HEIGHT/2,
$(mip_levels) = 1,
$(layer_count) = 1
);
$(width) = WIDTH/2, $(height) = HEIGHT/2,
$(mip_levels), $(layer_count));
texture0.CreateImageView(dev.device, p010?VK_FORMAT_R16_UNORM:VK_FORMAT_R8_UNORM);
texture1.CreateImageView(dev.device, p010?VK_FORMAT_R16G16_UNORM:VK_FORMAT_R8G8_UNORM);
}
@ -210,9 +189,7 @@ struct ComputeApplication {
/*
We create a fence.
*/
VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = 0;
$Sc fenceCreateInfo = FenceInfo();
VK_CHECK_RESULT(vkCreateFence(dev.device, &fenceCreateInfo, NULL, &chain[chidx].fence));
}
@ -224,31 +201,11 @@ struct ComputeApplication {
}
void runCommandBuffer(int chidx) {
/*
Now we shall finally submit the recorded command buffer to a queue.
*/
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1; // submit a single command buffer
submitInfo.pCommandBuffers = &chain[chidx].commandBuffer; // the command buffer to submit.
$Sc submitInfo = SubmitInfo(chain[chidx].commandBuffer);
waitFence(chidx);
vkResetFences(dev.device, 1, &chain[chidx].fence);
/*
We submit the command buffer on the queue, at the same time giving a fence.
*/
VK_CHECK_RESULT(vkQueueSubmit(dev.defautQueue, 1, &submitInfo, chain[chidx].fence));
chain[chidx].running = true;
/*
The command will not have finished executing until the fence is signalled.
So we wait here.
We will directly after this read our buffer from the GPU,
and we will not be sure that the command has finished executing unless we wait for the fence.
Hence, we use a fence here.
*/
//VK_CHECK_RESULT(vkWaitForFences(device, 1, &fence, VK_TRUE, 100000000000));
}
template <typename Codec>
void run(bool p010, const char *filename) {
@ -260,19 +217,12 @@ struct ComputeApplication {
context.Create("streamingengine", "vulkan-playground", ENABLE_VALIDATION_LAYERS);
dev.Create(context.FindPhysicalDevice(), VK_QUEUE_COMPUTE_BIT);
dev.CreateDevice(context);
//createImageExportableDmabuf(image0, imageView0, imageMemory0, prime_fd, WIDTH, HEIGHT, VK_FORMAT_R8_UNORM);
//createImageExportableDmabuf(image1, imageView1, imageMemory1, prime_fd_uv, WIDTH/2, HEIGHT/2, VK_FORMAT_R8G8_UNORM);
int drm_fd = drm_fd = open("/dev/dri/renderD128", O_RDWR);
//auto *r = vaapi_recorder_create2(drm_fd, WIDTH, HEIGHT, "out.264", prime_fd, WIDTH * 4);
//auto *r = vaapi_recorder_create3(drm_fd, WIDTH, HEIGHT, "out.264", prime_fd, WIDTH * 4, prime_fd_uv, WIDTH * 2);
uint64_t mod;
uint32_t size, offset, pitch1, pitch2;
int fd[CHAIN_SIZE];
uint64_t modifiers[32];
int count = dev.GetAvailiableModifiersList(modifiers, 32, p010?VK_FORMAT_R16_UNORM:VK_FORMAT_R8_UNORM);
//auto *r = vaapi_recorder_create5(drm_fd, WIDTH, HEIGHT, "out.264", fd, &mod, &size, &offset, &pitch1, &pitch2, modifiers, count);
Codec enc = {};
enc.Setup(drm_fd, WIDTH, HEIGHT, filename, fd, &mod, &size, &offset, &pitch1, &pitch2, modifiers, count, p010);
@ -311,24 +261,11 @@ struct ComputeApplication {
{
waitFence(i);
vkDestroyFence(dev.device, chain[i].fence, NULL);
//vkFreeMemory(dev.device, chain[i].texture0.device_memory, NULL);
//vkFreeMemory(device, chain[i].imageMemory1, NULL);
chain[i].uboBuf.Destroy();
chain[i].texture1.Destroy();
chain[i].texture0.Destroy();
/*vkDestroyImageView(dev.device, chain[i].texture0.view, NULL);
vkDestroyImage(dev.device, chain[i].texture0.image, NULL);
vkDestroyImageView(dev.device, chain[i].texture1.view, NULL);
vkDestroyImage(dev.device, chain[i].texture1.image, NULL);*/
}
// Clean up all vulkan resources.
cleanup();
}
void cleanup() {
/*
Clean up all Vulkan Resources.
*/
computePipeline.Destroy();
dev.Destroy();
context.Destroy();

View file

@ -291,12 +291,6 @@ struct GraphicsApplication
{
commandBuffers[i] = dev.CreateCommandBuffer();
//VulkanTexture::SetImageLayout(commandBuffers[i], swapchainImages[i], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
VkClearColorValue color;
color.uint32[0] = 45243524;
color.uint32[1] = 45234545;
color.uint32[2] = 54353453;
//vkCmdClearColorImage(commandBuffers[i], swapchainImages[i],VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, &color, 1, &range );
swapchainFbs[i].BeginRenderPass(commandBuffers[i]);
swapchainFbs[i].SetViewportAndScissor(commandBuffers[i]);
@ -325,7 +319,6 @@ struct GraphicsApplication
idx = AcquireImage(sem_idx);
VkSubmitInfo submitInfo = {VK_STRUCTURE_TYPE_SUBMIT_INFO};
submitInfo.pWaitSemaphores = &swapchainRenderSemaphore[sem_idx];
submitInfo.waitSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &swapchainPresentSemaphore[idx];

117
vulkan_contructors.h Normal file
View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 2024 mittorn
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef VULKAN_CONTRUCTORS_H
#define VULKAN_CONTRUCTORS_H
#include <vulkan/vulkan.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#ifndef VK_CHECK_RESULT
#define VK_CHECK_RESULT(f) \
{ \
VkResult res = (f); \
if (res != VK_SUCCESS) \
{ \
printf("Fatal : VkResult is %d in %s at line %d\n", res, __FILE__, __LINE__); \
assert(res == VK_SUCCESS); \
} \
}
#endif
#include "positional_utl.h"
template <typename... Args>
VkImageCreateInfo Image2dInfo(VkImageUsageFlags usage, VkFormat format, uint32_t width, uint32_t height, const Args&... arguments)
{
return $M(VkImageCreateInfo{VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO},
$(imageType) = VK_IMAGE_TYPE_2D,
$(extent) = VkExtent3D{width, height, 1},
$(mipLevels), $(arrayLayers), $(samples),
$(usage) = usage, $(format) = format,
arguments...); // already set by initial zero: VK_SHARING_MODE_EXCLUSIVE, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_LAYOUT_UNDEFINED
}
VkMemoryAllocateInfo AllocateInfo(VkDeviceSize sz = 0, uint32_t idx = 0)
{
return $M(VkMemoryAllocateInfo{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO},
$(allocationSize) = sz, $(memoryTypeIndex) = idx);
}
template <typename... Args>
VkBufferCreateInfo BufferInfo(VkImageUsageFlags usage, VkDeviceSize size, const Args&... arguments)
{
return $M(VkBufferCreateInfo{VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO},
$(usage) = usage, $(size) = size, arguments...);
}
template <typename... Args>
VkImageSubresourceRange SubresourceRange(Args... arguments)
{
return $M(VkImageSubresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 },arguments...);
}
template <typename... Args>
VkSubresourceLayout SubresourceLayout(VkDeviceSize pitch, const Args&... arguments )
{
return $M(VkSubresourceLayout{0},$(rowPitch) = pitch,arguments...);
}
VkFenceCreateInfo FenceInfo(VkFenceCreateFlags flags = 0)
{
return $M(VkFenceCreateInfo{VK_STRUCTURE_TYPE_FENCE_CREATE_INFO}, $(flags) = flags);
}
template <typename... Args>
VkSubmitInfo SubmitInfo(const VkCommandBuffer &commandBuffer, const Args&... arguments)
{
return $M(VkSubmitInfo{VK_STRUCTURE_TYPE_SUBMIT_INFO},
$(commandBufferCount), $(pCommandBuffers) &= commandBuffer, arguments...);
}
// wrapper for chains with pNext
template <typename T, typename... Ts>
struct $Sc : T, $Sc<Ts...>
{
$Sc(const T &t, const Ts&... a) : T(t), $Sc<Ts...>(a...)
{
((T*)this)->pNext = ($Sc<Ts...>*)this;
}
};
template <typename T>
struct $Sc<T> : T
{
$Sc(const T &t) : T(t){}
};
#ifndef DISABLE_STRUCTURE_MAP
#include <vulkan/generated/vk_typemap_helper.h>
template <typename T, typename... Ts>
T $Vk(const Ts&... ts)
{
T t = LvlInitStruct<T>();
$F(t, ts...);
return t;
}
#endif
#endif // VULKAN_CONTRUCTORS_H