vulkan UI
This commit is contained in:
parent
f8e142fb06
commit
177f873639
13 changed files with 455 additions and 37 deletions
Binary file not shown.
Binary file not shown.
|
|
@ -7,13 +7,9 @@
|
|||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-win32-vulkan-debug"
|
||||
"configuration":"lib-wayland-vulkan-debug"
|
||||
}
|
||||
],
|
||||
"march": "x86-64-v3",
|
||||
"mtune": "generic",
|
||||
"target": "x86_64-w64-mingw32",
|
||||
"debug": false,
|
||||
"shaders": [
|
||||
{
|
||||
"path":"raygen.glsl",
|
||||
|
|
|
|||
230
examples/VulkanUI/main.cpp
Normal file
230
examples/VulkanUI/main.cpp
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
#include "vulkan/vulkan.h"
|
||||
#include <cassert>
|
||||
|
||||
import Crafter.Graphics;
|
||||
using namespace Crafter;
|
||||
import std;
|
||||
import Crafter.Event;
|
||||
import Crafter.Math;
|
||||
|
||||
|
||||
int main() {
|
||||
Device::Initialize();
|
||||
Window window(1280, 720, "HelloVulkan");
|
||||
VkCommandBuffer cmd = window.StartInit();
|
||||
DescriptorHeapVulkan descriptorHeap;
|
||||
descriptorHeap.Initialize(1,1,0);
|
||||
|
||||
VkSpecializationMapEntry entry = {
|
||||
.constantID = 0,
|
||||
.offset = 0,
|
||||
.size = sizeof(uint16_t)
|
||||
};
|
||||
|
||||
VkSpecializationInfo specilizationInfo = {
|
||||
.mapEntryCount = 1,
|
||||
.pMapEntries = &entry,
|
||||
.dataSize = sizeof(uint16_t),
|
||||
.pData = &descriptorHeap.bufferStartElement
|
||||
};
|
||||
|
||||
std::array<VulkanShader, 1> shaders{{
|
||||
{"raygen.spv", "main", VK_SHADER_STAGE_RAYGEN_BIT_KHR, &specilizationInfo}
|
||||
}};
|
||||
|
||||
ShaderBindingTableVulkan shaderTable;
|
||||
shaderTable.Init(shaders);
|
||||
|
||||
std::array<VkRayTracingShaderGroupCreateInfoKHR, 1> raygenGroups {{
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR,
|
||||
.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR,
|
||||
.generalShader = 0,
|
||||
.closestHitShader = VK_SHADER_UNUSED_KHR,
|
||||
.anyHitShader = VK_SHADER_UNUSED_KHR,
|
||||
.intersectionShader = VK_SHADER_UNUSED_KHR,
|
||||
},
|
||||
}};
|
||||
std::array<VkRayTracingShaderGroupCreateInfoKHR, 0> missGroups;
|
||||
std::array<VkRayTracingShaderGroupCreateInfoKHR, 0> hitGroups;
|
||||
|
||||
|
||||
PipelineRTVulkan pipeline;
|
||||
pipeline.Init(cmd, raygenGroups, missGroups, hitGroups, shaderTable);
|
||||
|
||||
window.FinishInit();
|
||||
|
||||
RendertargetBase<3> rendertargetBase(1280, 720);
|
||||
RenderingElement2DVulkan<true, true> element(
|
||||
{
|
||||
0.5, //anchorX: relative position where this elements x anchor (top-left) is placed to its parent x anchor
|
||||
0.5, //anchorY: relative position where this elements y anchor (top-left) is placed to its parent y anchor
|
||||
0.5, //relativeSizeX: the relative x size this element should be scaled to compared to its parent
|
||||
0.5, //relativeSizeY: the relative y size this element should be scaled to compared to its parent
|
||||
0.5, //anchorOffsetX: the amount this element's anchor should be offset from the top left corner (0.5 to in the middle)
|
||||
0.5, //anchorOffsetY: the amount this element's anchor should be offset from the top left corner (0.5 to place it in the middle)
|
||||
0 //z: this elements Z position
|
||||
},
|
||||
2,
|
||||
1
|
||||
);
|
||||
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
||||
element.buffers[i]->value[0] = {1, 0, 0, 1};
|
||||
element.buffers[i]->value[1] = {0, 1, 0, 1};
|
||||
element.buffers[i]->FlushDevice();
|
||||
}
|
||||
|
||||
InitializeRenderingElement2DVulkanBuffer();
|
||||
element.UpdatePosition(rendertargetBase, rendertargetBase.transform);
|
||||
|
||||
renderingElement2DVulkanTransformBuffer[0].FlushDevice();
|
||||
renderingElement2DVulkanTransformBuffer[1].FlushDevice();
|
||||
renderingElement2DVulkanTransformBuffer[2].FlushDevice();
|
||||
|
||||
VkImageDescriptorInfoEXT imageInfo0 = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT,
|
||||
.pView = &window.imageViews[0],
|
||||
.layout = VK_IMAGE_LAYOUT_GENERAL
|
||||
};
|
||||
|
||||
VkImageDescriptorInfoEXT imageInfo1 = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT,
|
||||
.pView = &window.imageViews[1],
|
||||
.layout = VK_IMAGE_LAYOUT_GENERAL
|
||||
};
|
||||
|
||||
VkImageDescriptorInfoEXT imageInfo2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_DESCRIPTOR_INFO_EXT,
|
||||
.pView = &window.imageViews[2],
|
||||
.layout = VK_IMAGE_LAYOUT_GENERAL
|
||||
};
|
||||
|
||||
VkDeviceAddressRangeKHR transformRange0 = {
|
||||
.address = renderingElement2DVulkanTransformBuffer[0].address,
|
||||
.size = renderingElement2DVulkanTransformBuffer[0].descriptor.range
|
||||
};
|
||||
|
||||
VkDeviceAddressRangeKHR transformRange1 = {
|
||||
.address = renderingElement2DVulkanTransformBuffer[1].address,
|
||||
.size = renderingElement2DVulkanTransformBuffer[1].descriptor.range
|
||||
};
|
||||
|
||||
VkDeviceAddressRangeKHR transformRange2 = {
|
||||
.address = renderingElement2DVulkanTransformBuffer[2].address,
|
||||
.size = renderingElement2DVulkanTransformBuffer[2].descriptor.range
|
||||
};
|
||||
|
||||
VkDeviceAddressRangeKHR elRange0 = {
|
||||
.address = element.buffers[0]->address,
|
||||
.size = element.buffers[0]->descriptor.range
|
||||
};
|
||||
|
||||
VkDeviceAddressRangeKHR elRange1 = {
|
||||
.address = element.buffers[1]->address,
|
||||
.size = element.buffers[1]->descriptor.range
|
||||
};
|
||||
|
||||
VkDeviceAddressRangeKHR elRange2 = {
|
||||
.address = element.buffers[2]->address,
|
||||
.size = element.buffers[2]->descriptor.range
|
||||
};
|
||||
|
||||
VkResourceDescriptorInfoEXT resources[9] = {
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.data = { .pImage = &imageInfo0 }
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.data = { .pImage = &imageInfo1 }
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||
.data = { .pImage = &imageInfo2 }
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.data = { .pAddressRange = &transformRange0}
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.data = { .pAddressRange = &transformRange1}
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.data = { .pAddressRange = &transformRange2}
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.data = { .pAddressRange = &elRange0}
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.data = { .pAddressRange = &elRange1}
|
||||
},
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_RESOURCE_DESCRIPTOR_INFO_EXT,
|
||||
.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.data = { .pAddressRange = &elRange2}
|
||||
},
|
||||
};
|
||||
|
||||
VkHostAddressRangeEXT destinations[9] = {
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[0].value,
|
||||
.size = Device::descriptorHeapProperties.imageDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[1].value,
|
||||
.size = Device::descriptorHeapProperties.imageDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[2].value,
|
||||
.size = Device::descriptorHeapProperties.imageDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[0].value + descriptorHeap.bufferStartOffset,
|
||||
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[1].value + descriptorHeap.bufferStartOffset,
|
||||
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[2].value + descriptorHeap.bufferStartOffset,
|
||||
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[0].value + descriptorHeap.bufferStartOffset + Device::descriptorHeapProperties.bufferDescriptorSize * (renderingElement2DVulkans.size()),
|
||||
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[1].value + descriptorHeap.bufferStartOffset + Device::descriptorHeapProperties.bufferDescriptorSize * (renderingElement2DVulkans.size()),
|
||||
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
||||
},
|
||||
{
|
||||
.address = descriptorHeap.resourceHeap[2].value + descriptorHeap.bufferStartOffset + Device::descriptorHeapProperties.bufferDescriptorSize * (renderingElement2DVulkans.size()),
|
||||
.size = Device::descriptorHeapProperties.bufferDescriptorSize
|
||||
},
|
||||
};
|
||||
|
||||
Device::vkWriteResourceDescriptorsEXT(Device::device, 9, resources, destinations);
|
||||
|
||||
descriptorHeap.resourceHeap[0].FlushDevice();
|
||||
descriptorHeap.resourceHeap[1].FlushDevice();
|
||||
descriptorHeap.resourceHeap[2].FlushDevice();
|
||||
|
||||
window.pipeline = &pipeline;
|
||||
window.descriptorHeap = &descriptorHeap;
|
||||
|
||||
window.Render();
|
||||
window.StartSync();
|
||||
}
|
||||
23
examples/VulkanUI/project.json
Normal file
23
examples/VulkanUI/project.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "crafter-graphics",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-wayland-vulkan-debug"
|
||||
}
|
||||
],
|
||||
"debug": true,
|
||||
"shaders": [
|
||||
{
|
||||
"path":"raygen.glsl",
|
||||
"type": 6,
|
||||
"entrypoint":"main"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
48
examples/VulkanUI/raygen.glsl
Normal file
48
examples/VulkanUI/raygen.glsl
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#version 460
|
||||
#extension GL_EXT_ray_tracing : enable
|
||||
#extension GL_EXT_shader_image_load_formatted : enable
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_int16 : enable
|
||||
#extension GL_EXT_descriptor_heap : enable
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable
|
||||
|
||||
|
||||
struct UIScaledData{
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t sizeX;
|
||||
int16_t sizeY;
|
||||
uint16_t bufferX;
|
||||
uint16_t bufferY;
|
||||
};
|
||||
|
||||
layout(std430, descriptor_heap) buffer UIScaledDataBuffer {
|
||||
uint16_t count;
|
||||
uint16_t pad[5];
|
||||
UIScaledData data[];
|
||||
} UITransformBuffer[];
|
||||
|
||||
layout(std430, descriptor_heap) buffer UIPixelBufferr {
|
||||
f16vec4 pixels[];
|
||||
} UIPixelBuffer[];
|
||||
|
||||
layout(constant_id = 0) const uint16_t bufferStart = 0us;
|
||||
layout(descriptor_heap) uniform writeonly image2D image[];
|
||||
|
||||
void main()
|
||||
{
|
||||
uvec2 pixel = gl_LaunchIDEXT.xy;
|
||||
uvec2 resolution = gl_LaunchSizeEXT.xy;
|
||||
|
||||
vec4 hitValue = vec4(0);
|
||||
|
||||
for (uint16_t i = 1us; i < UITransformBuffer[bufferStart].count+1; i++) {
|
||||
if(pixel.x > UITransformBuffer[bufferStart].data[i].x && pixel.x < UITransformBuffer[bufferStart].data[i].x + UITransformBuffer[bufferStart].data[i].sizeX && pixel.y > UITransformBuffer[bufferStart].data[i].y && pixel.y < UITransformBuffer[bufferStart].data[i].y + UITransformBuffer[bufferStart].data[i].sizeY) {
|
||||
int16_t srcX = int16_t((pixel.x - UITransformBuffer[bufferStart].data[i].x) * UITransformBuffer[bufferStart].data[i].bufferX / UITransformBuffer[bufferStart].data[i].sizeX);
|
||||
int16_t srcY = int16_t((pixel.y - UITransformBuffer[bufferStart].data[i].y) * UITransformBuffer[bufferStart].data[i].bufferY / UITransformBuffer[bufferStart].data[i].sizeY);
|
||||
hitValue = vec4(UIPixelBuffer[bufferStart + UITransformBuffer[bufferStart].count].pixels[srcY * UITransformBuffer[bufferStart].data[i].bufferX + srcX]);
|
||||
}
|
||||
}
|
||||
|
||||
imageStore(image[0], ivec2(pixel), hitValue);
|
||||
}
|
||||
|
|
@ -70,7 +70,8 @@ const char* const deviceExtensionNames[] = {
|
|||
"VK_EXT_descriptor_heap",
|
||||
"VK_KHR_deferred_host_operations",
|
||||
"VK_KHR_maintenance5",
|
||||
"VK_KHR_shader_untyped_pointers"
|
||||
"VK_KHR_shader_untyped_pointers",
|
||||
"VK_EXT_device_fault"
|
||||
};
|
||||
const char* const layerNames[] = {
|
||||
"VK_LAYER_KHRONOS_validation"
|
||||
|
|
@ -80,6 +81,58 @@ const char* const layerNames[] = {
|
|||
void Device::CheckVkResult(VkResult result) {
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
if(result == VK_ERROR_DEVICE_LOST) {
|
||||
VkDeviceFaultCountsEXT faultCounts = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT,
|
||||
.pNext = NULL,
|
||||
};
|
||||
Device::vkGetDeviceFaultInfoEXT(device, &faultCounts, NULL);
|
||||
|
||||
std::vector<VkDeviceFaultAddressInfoEXT> addressInfos(faultCounts.addressInfoCount);
|
||||
std::vector<VkDeviceFaultVendorInfoEXT> vendorInfos(faultCounts.vendorInfoCount);
|
||||
std::vector<char> vendorBinaryData(faultCounts.vendorBinarySize);
|
||||
|
||||
VkDeviceFaultInfoEXT faultInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT,
|
||||
.pNext = NULL,
|
||||
.pAddressInfos = addressInfos.data(),
|
||||
.pVendorInfos = vendorInfos.data(),
|
||||
.pVendorBinaryData = vendorBinaryData.data(),
|
||||
};
|
||||
Device::vkGetDeviceFaultInfoEXT(device, &faultCounts, &faultInfo);
|
||||
|
||||
std::println("{}", faultInfo.description);
|
||||
|
||||
std::println("{} AddressInfos:", addressInfos.size());
|
||||
for(const VkDeviceFaultAddressInfoEXT& info : addressInfos) {
|
||||
std::println("\t{} {}", static_cast<uint32_t>(info.addressType), info.reportedAddress);
|
||||
}
|
||||
|
||||
std::println("{} vendorInfos:", vendorInfos.size());
|
||||
for(const VkDeviceFaultVendorInfoEXT& info : vendorInfos) {
|
||||
std::println("\t{} {} {}", info.description, info.vendorFaultCode, info.vendorFaultData);
|
||||
}
|
||||
|
||||
if(!vendorBinaryData.empty()) {
|
||||
std::string ext = ".bin";
|
||||
if(vendorBinaryData.size() >= sizeof(VkDeviceFaultVendorBinaryHeaderVersionOneEXT)) {
|
||||
VkDeviceFaultVendorBinaryHeaderVersionOneEXT header;
|
||||
std::memcpy(&header, vendorBinaryData.data(), sizeof(header));
|
||||
if(header.vendorID == 0x10DE) { // NVIDIA
|
||||
ext = ".nv-gpudmp";
|
||||
}
|
||||
}
|
||||
const auto now = std::chrono::system_clock::now();
|
||||
const std::string dumpPath = std::format("gpu_crash_dump-{:%Y%m%d-%H%M%S}{}", now, ext);
|
||||
std::ofstream file(dumpPath, std::ios::binary);
|
||||
if(file.write(vendorBinaryData.data(), vendorBinaryData.size())) {
|
||||
std::println("Vendor binary saved to: {}", std::filesystem::canonical(dumpPath).string());
|
||||
} else {
|
||||
std::println(stderr, "Failed to write vendor binary to: {}", dumpPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error(string_VkResult(result));
|
||||
}
|
||||
}
|
||||
|
|
@ -603,8 +656,24 @@ void Device::Initialize() {
|
|||
queueCreateInfo.queueCount = 1;
|
||||
queueCreateInfo.pQueuePriorities = &priority;
|
||||
|
||||
VkPhysicalDeviceFaultFeaturesEXT faultFeatures2 = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT,
|
||||
};
|
||||
VkPhysicalDeviceFeatures2 features22 = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
||||
.pNext = &faultFeatures2,
|
||||
};
|
||||
vkGetPhysicalDeviceFeatures2(physDevice, &features22);
|
||||
|
||||
VkPhysicalDeviceFaultFeaturesEXT faultFeatures = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT,
|
||||
.deviceFault = VK_TRUE,
|
||||
.deviceFaultVendorBinary = faultFeatures2.deviceFaultVendorBinary,
|
||||
};
|
||||
|
||||
VkPhysicalDeviceShaderUntypedPointersFeaturesKHR untypedPointersFeatures {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_UNTYPED_POINTERS_FEATURES_KHR,
|
||||
.pNext = &faultFeatures,
|
||||
.shaderUntypedPointers = VK_TRUE,
|
||||
};
|
||||
|
||||
|
|
@ -623,6 +692,7 @@ void Device::Initialize() {
|
|||
VkPhysicalDeviceVulkan12Features features12 {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
.pNext = &bit16,
|
||||
.shaderFloat16 = VK_TRUE,
|
||||
.runtimeDescriptorArray = VK_TRUE,
|
||||
.bufferDeviceAddress = VK_TRUE
|
||||
};
|
||||
|
|
@ -703,6 +773,7 @@ void Device::Initialize() {
|
|||
vkCmdBindSamplerHeapEXT = reinterpret_cast<PFN_vkCmdBindSamplerHeapEXT>(vkGetInstanceProcAddr(instance, "vkCmdBindSamplerHeapEXT"));
|
||||
vkWriteResourceDescriptorsEXT = reinterpret_cast<PFN_vkWriteResourceDescriptorsEXT>(vkGetInstanceProcAddr(instance, "vkWriteResourceDescriptorsEXT"));
|
||||
vkGetPhysicalDeviceDescriptorSizeEXT = reinterpret_cast<PFN_vkGetPhysicalDeviceDescriptorSizeEXT>(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceDescriptorSizeEXT"));
|
||||
vkGetDeviceFaultInfoEXT = reinterpret_cast<PFN_vkGetDeviceFaultInfoEXT>(vkGetInstanceProcAddr(instance, "vkGetDeviceFaultInfoEXT"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ export namespace Crafter {
|
|||
inline static PFN_vkCmdBindSamplerHeapEXT vkCmdBindSamplerHeapEXT;
|
||||
inline static PFN_vkWriteResourceDescriptorsEXT vkWriteResourceDescriptorsEXT;
|
||||
inline static PFN_vkGetPhysicalDeviceDescriptorSizeEXT vkGetPhysicalDeviceDescriptorSizeEXT;
|
||||
inline static PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT;
|
||||
|
||||
inline static VkPhysicalDeviceMemoryProperties memoryProperties;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
module;
|
||||
#include "../lib/stb_truetype.h"
|
||||
#ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
export module Crafter.Graphics:RenderingElement2DVulkan;
|
||||
#ifdef CRAFTER_GRAPHICS_RENDERER_VULKAN
|
||||
import Crafter.Asset;
|
||||
import std;
|
||||
import :Transform2D;
|
||||
import :VulkanBuffer;
|
||||
import :Types;
|
||||
import :Window;
|
||||
|
||||
|
|
@ -32,44 +37,85 @@ export namespace Crafter {
|
|||
std::uint16_t bufferX; // 8 - 2 bytes
|
||||
std::uint16_t bufferY; // 10 - 2 bytes
|
||||
//12 bytes total;
|
||||
}
|
||||
};
|
||||
|
||||
struct RenderingElement2DVulkanBase : Transform2D {
|
||||
std::uint16_t index;
|
||||
std::uint16_t bufferX;
|
||||
std::uint16_t bufferY;
|
||||
RenderingElement2DVulkanBase(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY) : bufferX(bufferX), bufferY(bufferY), Transform2D(anchor) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<RenderingElement2DVulkanBase*> renderingElement2DVulkans;
|
||||
VulkanBuffer<RenderingElement2DVulkanTransformInfo, true, true> renderingElement2DVulkanTransformBuffer[Window::numFrames];
|
||||
|
||||
template<bool Owning, bool Mapped>
|
||||
struct RenderingElement2DVulkan {
|
||||
std::uint16_t index;
|
||||
std:array<VulkanBuffer<_Float16, Mapped, false>*, Window::NumFrames> buffers;
|
||||
RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferWidth, std::uint16_t bufferHeight) requires(Owning) : index(renderingElement2DVulkans.size()-1) {
|
||||
struct RenderingElement2DVulkan : RenderingElement2DVulkanBase {
|
||||
std::array<VulkanBuffer<Vector<_Float16, 4, 4>, Mapped, true>*, Window::numFrames> buffers;
|
||||
RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY) requires(Owning) : RenderingElement2DVulkanBase(anchor, bufferX, bufferY) {
|
||||
renderingElement2DVulkans.push_back(this);
|
||||
for(std::uint8_t i = 0; i < Window::numFrames; i++) {
|
||||
buffers[i] = new VulkanBuffer<Vector<_Float16, 4, 4>, Mapped, true>();
|
||||
buffers[i]->Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bufferX * bufferY);
|
||||
}
|
||||
}
|
||||
RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferWidth, std::uint16_t bufferHeight, std:array<VulkanBuffer<_Float16, Mapped, false>*, Window::NumFrames> buffers) requires(!Owning) : buffers(buffers) {
|
||||
RenderingElement2DVulkan(Anchor2D anchor, std::uint16_t bufferX, std::uint16_t bufferY, std::array<VulkanBuffer<_Float16, Mapped, true>*, Window::numFrames> buffers) requires(!Owning) : buffers(buffers), RenderingElement2DVulkanBase(anchor, bufferX, bufferY) {
|
||||
renderingElement2DVulkans.push_back(this);
|
||||
}
|
||||
|
||||
~RenderingElement2DVulkan() {
|
||||
if constexpr(Owning) {
|
||||
for(VulkanBuffer<_Float16, Mapped, false>* buffer : buffers) {
|
||||
for(VulkanBuffer<Vector<_Float16, 4, 4>, Mapped, true>* buffer : buffers) {
|
||||
delete buffer;
|
||||
}
|
||||
}
|
||||
auto it = std::find(renderingElement2DVulkans.begin(), renderingElement2DVulkans.end(), this);
|
||||
if (it != renderingElement2DVulkans.end()) {
|
||||
renderingElement2DVulkans.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
RenderingElement2DVulkan(RenderingElement2DVulkan&) = delete;
|
||||
RenderingElement2DVulkan& operator=(RenderingElement2DVulkan&) = delete;
|
||||
|
||||
void UpdatePosition(RendertargetBase<Frames>& window, Transform2D& parent) override {
|
||||
ScaleData2D oldScale = this->scaled;
|
||||
void UpdatePosition(RendertargetBase<Window::numFrames>& window, Transform2D& parent) override {
|
||||
this->ScaleElement(parent);
|
||||
if(oldScale.size.x != this->scaled.size.x || oldScale.size.y != this->scaled.size.y) {
|
||||
this->buffer.resize(this->scaled.size.x * this->scaled.size.y);
|
||||
}
|
||||
RenderingElement2DVulkanTransformInfo* val = reinterpret_cast<RenderingElement2DVulkanTransformInfo*>(reinterpret_cast<char*>(renderingElement2DVulkanTransformBuffer[window.frame].value) + sizeof(RenderingElement2DVulkanTransformInfo));
|
||||
val[index].scaled = this->scaled;
|
||||
for(Transform2D* child : this->children) {
|
||||
child->UpdatePosition(window, *this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline static std::vector<RenderingElement2DVulkan*> renderingElement2DVulkans;
|
||||
inline static std::vector<VkDescriptorBufferInfo> renderingElement2DVulkanDescriptors[Window::NumFrames];
|
||||
inline static VulkanBuffer<RenderingElement2DVulkanTransformInfo, Mapped, false>* renderingElement2DVulkanTransformBuffer[Window::NumFrames];
|
||||
void InitializeRenderingElement2DVulkanBuffer() {
|
||||
for(std::uint8_t frame = 0; frame < Window::numFrames; frame++) {
|
||||
renderingElement2DVulkanTransformBuffer[frame].Create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, renderingElement2DVulkans.size()+1);
|
||||
RenderingElement2DVulkanTransformInfo* val = reinterpret_cast<RenderingElement2DVulkanTransformInfo*>(reinterpret_cast<char*>(renderingElement2DVulkanTransformBuffer[frame].value) + sizeof(RenderingElement2DVulkanTransformInfo));
|
||||
std::uint16_t* sizePtr = reinterpret_cast<std::uint16_t*>(renderingElement2DVulkanTransformBuffer[frame].value);
|
||||
*sizePtr = renderingElement2DVulkans.size();
|
||||
for(std::uint16_t i = 0; i < renderingElement2DVulkans.size(); i++) {
|
||||
val[i].scaled = renderingElement2DVulkans[i]->scaled;
|
||||
val[i].bufferX = renderingElement2DVulkans[i]->bufferX;
|
||||
val[i].bufferY = renderingElement2DVulkans[i]->bufferY;
|
||||
renderingElement2DVulkans[i]->index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateRenderingElement2DVulkanBuffer(std::uint8_t frame) {
|
||||
renderingElement2DVulkanTransformBuffer[frame].Resize(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_2_SHADER_DEVICE_ADDRESS_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, renderingElement2DVulkans.size()+1);
|
||||
RenderingElement2DVulkanTransformInfo* val = reinterpret_cast<RenderingElement2DVulkanTransformInfo*>(reinterpret_cast<char*>(renderingElement2DVulkanTransformBuffer[frame].value) + sizeof(RenderingElement2DVulkanTransformInfo));
|
||||
std::uint16_t* sizePtr = reinterpret_cast<std::uint16_t*>(renderingElement2DVulkanTransformBuffer[frame].value);
|
||||
*sizePtr = renderingElement2DVulkans.size();
|
||||
for(std::uint16_t i = 0; i < renderingElement2DVulkans.size(); i++) {
|
||||
val[i].scaled = renderingElement2DVulkans[i]->scaled;
|
||||
val[i].bufferX = renderingElement2DVulkans[i]->bufferX;
|
||||
val[i].bufferY = renderingElement2DVulkans[i]->bufferY;
|
||||
renderingElement2DVulkans[i]->index = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -33,6 +33,7 @@ export namespace Crafter {
|
|||
Transform2D transform;
|
||||
std::uint16_t sizeX;
|
||||
std::uint16_t sizeY;
|
||||
std::uint8_t frame;
|
||||
RendertargetBase() = default;
|
||||
RendertargetBase(std::uint16_t sizeX, std::uint16_t sizeY) : sizeX(sizeX), sizeY(sizeY), transform({0, 0, 1, 1, 0, 0, 0}){
|
||||
transform.scaled.size.x = sizeX;
|
||||
|
|
@ -61,8 +62,8 @@ export namespace Crafter {
|
|||
}
|
||||
|
||||
for(ClipRect dirty : dirtyRects) {
|
||||
dirty.left = std::max(element->scaled.position.x, dirty.left);
|
||||
dirty.top = std::max(element->scaled.position.y, dirty.top);
|
||||
dirty.left = std::uint16_t(std::max(element->scaled.position.x, std::int16_t(dirty.left)));
|
||||
dirty.top = std::uint16_t(std::max(element->scaled.position.y,std::int16_t(dirty.top)));
|
||||
dirty.right = std::min(std::uint16_t(element->scaled.position.x+element->scaled.size.x), dirty.right);
|
||||
dirty.bottom = std::min(std::uint16_t(element->scaled.position.y+element->scaled.size.y), dirty.bottom);
|
||||
|
||||
|
|
@ -147,16 +148,16 @@ export namespace Crafter {
|
|||
void AddOldRects(Transform2D* elementTransform, std::uint8_t frame, std::vector<ClipRect>& clipRects) {
|
||||
RenderingElement2DBase<T, Frames>* element = dynamic_cast<RenderingElement2DBase<T, Frames>*>(elementTransform);
|
||||
if(element) {
|
||||
if(element->scaled.position.x != element->oldScale[frame].position.x || element->scaled.position.y != element->oldScale[frame].position.y || element->scaled.size.x != element->oldScale[frame].size.x || element->scaled.size.y != element->oldScale[frame].size.y || element->redraw[frame]) {
|
||||
clipRects.emplace_back(std::max(element->scaled.position.x, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.x + element->scaled.size.x), this->sizeX), std::max(element->scaled.position.y, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.y + element->scaled.size.y), this->sizeY));
|
||||
clipRects.emplace_back(std::max(element->oldScale[frame].position.x, std::uint16_t(0)), std::min(std::uint16_t(element->oldScale[frame].position.x + element->oldScale[frame].size.x), this->sizeX), std::max(element->oldScale[frame].position.y, std::uint16_t(0)), std::min(std::uint16_t(element->oldScale[frame].position.y + element->oldScale[frame].size.y), this->sizeY));
|
||||
element->oldScale[frame] = element->scaled;
|
||||
element->redraw[frame] = false;
|
||||
} else if(element->redraw[frame]) {
|
||||
clipRects.emplace_back(std::max(element->scaled.position.x, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.x + element->scaled.size.x), this->sizeX), std::max(element->scaled.position.y, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.y + element->scaled.size.y), this->sizeY));
|
||||
element->oldScale[frame] = element->scaled;
|
||||
element->redraw[frame] = false;
|
||||
}
|
||||
// if(element->scaled.position.x != element->oldScale[frame].position.x || element->scaled.position.y != element->oldScale[frame].position.y || element->scaled.size.x != element->oldScale[frame].size.x || element->scaled.size.y != element->oldScale[frame].size.y || element->redraw[frame]) {
|
||||
// clipRects.emplace_back(std::max(element->scaled.position.x, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.x + element->scaled.size.x), this->sizeX), std::max(element->scaled.position.y, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.y + element->scaled.size.y), this->sizeY));
|
||||
// clipRects.emplace_back(std::max(element->oldScale[frame].position.x, std::uint16_t(0)), std::min(std::uint16_t(element->oldScale[frame].position.x + element->oldScale[frame].size.x), this->sizeX), std::max(element->oldScale[frame].position.y, std::uint16_t(0)), std::min(std::uint16_t(element->oldScale[frame].position.y + element->oldScale[frame].size.y), this->sizeY));
|
||||
// element->oldScale[frame] = element->scaled;
|
||||
// element->redraw[frame] = false;
|
||||
// } else if(element->redraw[frame]) {
|
||||
// clipRects.emplace_back(std::max(element->scaled.position.x, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.x + element->scaled.size.x), this->sizeX), std::max(element->scaled.position.y, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.y + element->scaled.size.y), this->sizeY));
|
||||
// element->oldScale[frame] = element->scaled;
|
||||
// element->redraw[frame] = false;
|
||||
// }
|
||||
}
|
||||
for(Transform2D* child : elementTransform->children) {
|
||||
AddOldRects(child, frame, clipRects);
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ export namespace Crafter {
|
|||
};
|
||||
|
||||
struct ScaleData2D {
|
||||
Vector<std::uint16_t, 2, 2> position;
|
||||
Vector<std::uint16_t, 2, 2> size;
|
||||
Vector<std::int16_t, 2, 2> position;
|
||||
Vector<std::int16_t, 2, 2> size;
|
||||
};
|
||||
|
||||
struct ClipRect {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ export import :RenderingElement3D;
|
|||
export import :ImageVulkan;
|
||||
export import :SamplerVulkan;
|
||||
export import :DescriptorHeapVulkan;
|
||||
export import :RenderingElement2DVulkan;
|
||||
#endif
|
||||
|
||||
// export import :WindowWaylandVulkan;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@
|
|||
"interfaces/Crafter.Graphics-SamplerVulkan",
|
||||
"interfaces/Crafter.Graphics-DescriptorHeapVulkan",
|
||||
"interfaces/Crafter.Graphics-Rendertarget",
|
||||
"interfaces/Crafter.Graphics-ForwardDeclarations"
|
||||
"interfaces/Crafter.Graphics-ForwardDeclarations",
|
||||
"interfaces/Crafter.Graphics-RenderingElement2DVulkan"
|
||||
],
|
||||
"type": "library"
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue