diff --git a/.clang-format b/.clang-format index 08a1404c..0a8a2320 100644 --- a/.clang-format +++ b/.clang-format @@ -33,4 +33,6 @@ BraceWrapping: BeforeElse: false IndentBraces: false +InsertBraces: true + CommentPragmas: '/\*(.+\n.+)+\*/' diff --git a/CMakeLists.txt b/CMakeLists.txt index d896aa89..2d9bd743 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ cmake_minimum_required(VERSION 3.22) -set(WISDOM_VERSION "0.4.0") +set(WISDOM_VERSION "0.5.0") project("Wisdom" VERSION ${WISDOM_VERSION}) set(CMAKE_DEBUG_POSTFIX d) diff --git a/CMakePresets.json b/CMakePresets.json index 5095527a..d229465e 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -99,6 +99,22 @@ "CMAKE_CXX_COMPILER": "cl.exe" } }, + { + "name": "x64-vs", + "displayName": "x64 VS", + "description": "Target Windows (64-bit) with the Visual Studio development environment. (Debug)", + "architecture": { + "value": "x64", + "strategy": "external" + }, + "generator": "Visual Studio 17 2022", + "cacheVariables": { + "WISDOM_GENERATE_FUNCTIONS": false, + "CMAKE_C_COMPILER": "cl.exe", + "CMAKE_CXX_COMPILER": "cl.exe", + "CMAKE_BUILD_TYPE": "Debug" + } + }, { "name": "x64-debug-only-lib", "displayName": "x64 Lib Debug", diff --git a/Changelog.md b/Changelog.md index 4aa55c63..dee71b98 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,13 @@ # Version History +- 0.5.0 API stabilization + + - Most of the API is now stable and will not change + - There are 2 versions of return values. One is the ResultValue<> which was there from the beginning, and the other is RVO enabled return value. ResultValue<> is left for compatibility and local use, while RVO enabled return value is for inline construction and chaining. It is recommended to use RVO enabled return value for all new code. + - Added documentation for extended allocation. With Vulkan 1.4 it has become a core feature. + - API structure is consistent. Now all the structures are passed by const reference. This is done to enable language interop. + - Consumed headers are now .hpp instead of .h. Implementation headers are still .h, since they are not intended to be used standalone anyway. + - 0.4.0 Major Update - Fixed Vulkan Swapchain on resize occasionally result in error messages diff --git a/LICENSE.txt b/LICENSE.txt index 8aa26455..efb5b636 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ MIT License -Copyright (c) [year] [fullname] +Copyright (c) 2024 Ilya "Agrael" Doroshenko Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/bindings/wisdom.cpp b/bindings/wisdom.cpp index 8b74be24..311919c0 100644 --- a/bindings/wisdom.cpp +++ b/bindings/wisdom.cpp @@ -35,12 +35,14 @@ extern "C" WisResult DX12FactoryGetAdapter(DX12Factory self, uint32_t index, Wis auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->GetAdapter(index, static_cast(preference)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *adapter = reinterpret_cast(new (std::nothrow) wis::DX12Adapter(std::move(value))); - if (!*adapter) + if (!*adapter) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Adapter." }; + } return reinterpret_cast(res); } @@ -78,12 +80,14 @@ extern "C" WisResult DX12DeviceCreateFence(DX12Device self, uint64_t initial_val auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateFence(initial_value, static_cast(flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *fence = reinterpret_cast(new (std::nothrow) wis::DX12Fence(std::move(value))); - if (!*fence) + if (!*fence) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Fence." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12DeviceCreateCommandQueue(DX12Device self, WisQueueType type, DX12CommandQueue* queue) @@ -91,12 +95,14 @@ extern "C" WisResult DX12DeviceCreateCommandQueue(DX12Device self, WisQueueType auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateCommandQueue(static_cast(type)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *queue = reinterpret_cast(new (std::nothrow) wis::DX12CommandQueue(std::move(value))); - if (!*queue) + if (!*queue) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12CommandQueue." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12DeviceCreateCommandList(DX12Device self, WisQueueType type, DX12CommandList* list) @@ -104,25 +110,29 @@ extern "C" WisResult DX12DeviceCreateCommandList(DX12Device self, WisQueueType t auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateCommandList(static_cast(type)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *list = reinterpret_cast(new (std::nothrow) wis::DX12CommandList(std::move(value))); - if (!*list) + if (!*list) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12CommandList." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12DeviceCreateGraphicsPipeline(DX12Device self, const DX12GraphicsPipelineDesc* desc, DX12PipelineState* pipeline) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateGraphicsPipeline(reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateGraphicsPipeline(*reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *pipeline = reinterpret_cast(new (std::nothrow) wis::DX12PipelineState(std::move(value))); - if (!*pipeline) + if (!*pipeline) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12PipelineState." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12DeviceCreateRootSignature(DX12Device self, const WisPushConstant* push_constants, uint32_t constants_count, const WisPushDescriptor* push_descriptors, uint32_t descriptors_count, uint32_t space_overlap_count, DX12RootSignature* signature) @@ -130,12 +140,14 @@ extern "C" WisResult DX12DeviceCreateRootSignature(DX12Device self, const WisPus auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateRootSignature(reinterpret_cast(push_constants), constants_count, reinterpret_cast(push_descriptors), descriptors_count, space_overlap_count); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *signature = reinterpret_cast(new (std::nothrow) wis::DX12RootSignature(std::move(value))); - if (!*signature) + if (!*signature) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12RootSignature." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12DeviceCreateRootSignature2(DX12Device self, const WisPushConstant* push_constants, uint32_t constants_count, const WisPushDescriptor* push_descriptors, uint32_t push_descriptors_count, const WisDescriptorSpacing* descriptor_spacing, DX12RootSignature* signature) @@ -143,12 +155,14 @@ extern "C" WisResult DX12DeviceCreateRootSignature2(DX12Device self, const WisPu auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateRootSignature2(reinterpret_cast(push_constants), constants_count, reinterpret_cast(push_descriptors), push_descriptors_count, reinterpret_cast(descriptor_spacing)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *signature = reinterpret_cast(new (std::nothrow) wis::DX12RootSignature(std::move(value))); - if (!*signature) + if (!*signature) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12RootSignature." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12DeviceCreateShader(DX12Device self, void* data, uint32_t size, DX12Shader* shader) @@ -156,12 +170,14 @@ extern "C" WisResult DX12DeviceCreateShader(DX12Device self, void* data, uint32_ auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateShader(data, size); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *shader = reinterpret_cast(new (std::nothrow) wis::DX12Shader(std::move(value))); - if (!*shader) + if (!*shader) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Shader." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12DeviceCreateAllocator(DX12Device self, DX12ResourceAllocator* allocator) @@ -169,64 +185,89 @@ extern "C" WisResult DX12DeviceCreateAllocator(DX12Device self, DX12ResourceAllo auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateAllocator(); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *allocator = reinterpret_cast(new (std::nothrow) wis::DX12ResourceAllocator(std::move(value))); - if (!*allocator) + if (!*allocator) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12ResourceAllocator." }; + } return reinterpret_cast(res); } -extern "C" WisResult DX12DeviceCreateRenderTarget(DX12Device self, DX12Texture texture, WisRenderTargetDesc desc, DX12RenderTarget* target) +extern "C" WisResult DX12DeviceCreateRenderTarget(DX12Device self, DX12Texture texture, const WisRenderTargetDesc* desc, DX12RenderTarget* target) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateRenderTarget(*reinterpret_cast(texture), reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateRenderTarget(*reinterpret_cast(texture), *reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *target = reinterpret_cast(new (std::nothrow) wis::DX12RenderTarget(std::move(value))); - if (!*target) + if (!*target) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12RenderTarget." }; + } return reinterpret_cast(res); } -extern "C" WisResult DX12DeviceCreateDepthStencilTarget(DX12Device self, DX12Texture texture, WisRenderTargetDesc desc, DX12RenderTarget* target) +extern "C" WisResult DX12DeviceCreateDepthStencilTarget(DX12Device self, DX12Texture texture, const WisRenderTargetDesc* desc, DX12RenderTarget* target) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateDepthStencilTarget(*reinterpret_cast(texture), reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateDepthStencilTarget(*reinterpret_cast(texture), *reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *target = reinterpret_cast(new (std::nothrow) wis::DX12RenderTarget(std::move(value))); - if (!*target) + if (!*target) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12RenderTarget." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12DeviceCreateSampler(DX12Device self, const WisSamplerDesc* desc, DX12Sampler* sampler) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateSampler(reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateSampler(*reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *sampler = reinterpret_cast(new (std::nothrow) wis::DX12Sampler(std::move(value))); - if (!*sampler) + if (!*sampler) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Sampler." }; + } return reinterpret_cast(res); } -extern "C" WisResult DX12DeviceCreateShaderResource(DX12Device self, DX12Texture texture, WisShaderResourceDesc desc, DX12ShaderResource* resource) +extern "C" WisResult DX12DeviceCreateShaderResource(DX12Device self, DX12Texture texture, const WisShaderResourceDesc* desc, DX12ShaderResource* resource) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateShaderResource(*reinterpret_cast(texture), reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateShaderResource(*reinterpret_cast(texture), *reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *resource = reinterpret_cast(new (std::nothrow) wis::DX12ShaderResource(std::move(value))); - if (!*resource) + if (!*resource) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12ShaderResource." }; + } + return reinterpret_cast(res); +} +extern "C" WisResult DX12DeviceCreateDescriptorStorage(DX12Device self, const WisDescriptorStorageDesc* desc, DX12DescriptorStorage* storage) +{ + auto* xself = reinterpret_cast(self); + auto&& [res, value] = xself->CreateDescriptorStorage(*reinterpret_cast(desc)); + + if (res.status != wis::Status::Ok) { + return reinterpret_cast(res); + } + + *storage = reinterpret_cast(new (std::nothrow) wis::DX12DescriptorStorage(std::move(value))); + if (!*storage) { + return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12DescriptorStorage." }; + } return reinterpret_cast(res); } extern "C" bool DX12DeviceQueryFeatureSupport(DX12Device self, WisDeviceFeature feature) @@ -248,12 +289,14 @@ extern "C" WisResult DX12ResourceAllocatorCreateBuffer(DX12ResourceAllocator sel auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateBuffer(size, static_cast(usage), static_cast(memory), static_cast(mem_flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *buffer = reinterpret_cast(new (std::nothrow) wis::DX12Buffer(std::move(value))); - if (!*buffer) + if (!*buffer) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Buffer." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12ResourceAllocatorCreateTexture(DX12ResourceAllocator self, const WisTextureDesc* desc, WisMemoryType memory, WisMemoryFlags mem_flags, DX12Texture* texture) @@ -261,12 +304,44 @@ extern "C" WisResult DX12ResourceAllocatorCreateTexture(DX12ResourceAllocator se auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateTexture(*reinterpret_cast(desc), static_cast(memory), static_cast(mem_flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *texture = reinterpret_cast(new (std::nothrow) wis::DX12Texture(std::move(value))); - if (!*texture) + if (!*texture) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Texture." }; + } + return reinterpret_cast(res); +} +extern "C" WisResult DX12ResourceAllocatorCreateUploadBuffer(DX12ResourceAllocator self, uint64_t size, DX12Buffer* buffer) +{ + auto* xself = reinterpret_cast(self); + auto&& [res, value] = xself->CreateUploadBuffer(size); + + if (res.status != wis::Status::Ok) { + return reinterpret_cast(res); + } + + *buffer = reinterpret_cast(new (std::nothrow) wis::DX12Buffer(std::move(value))); + if (!*buffer) { + return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Buffer." }; + } + return reinterpret_cast(res); +} +extern "C" WisResult DX12ResourceAllocatorCreateReadbackBuffer(DX12ResourceAllocator self, uint64_t size, DX12Buffer* buffer) +{ + auto* xself = reinterpret_cast(self); + auto&& [res, value] = xself->CreateReadbackBuffer(size); + + if (res.status != wis::Status::Ok) { + return reinterpret_cast(res); + } + + *buffer = reinterpret_cast(new (std::nothrow) wis::DX12Buffer(std::move(value))); + if (!*buffer) { + return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Buffer." }; + } return reinterpret_cast(res); } extern "C" WisAllocationInfo DX12ResourceAllocatorGetTextureAllocationInfo(DX12ResourceAllocator self, const WisTextureDesc* desc) @@ -288,12 +363,14 @@ extern "C" WisResult DX12ResourceAllocatorAllocateTextureMemory(DX12ResourceAllo auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->AllocateTextureMemory(size, static_cast(usage), static_cast(mem_type), static_cast(mem_flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *out_memory = reinterpret_cast(new (std::nothrow) wis::DX12Memory(std::move(value))); - if (!*out_memory) + if (!*out_memory) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Memory." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12ResourceAllocatorAllocateBufferMemory(DX12ResourceAllocator self, uint64_t size, WisBufferUsage usage, WisMemoryType mem_type, WisMemoryFlags mem_flags, DX12Memory* out_memory) @@ -301,12 +378,14 @@ extern "C" WisResult DX12ResourceAllocatorAllocateBufferMemory(DX12ResourceAlloc auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->AllocateBufferMemory(size, static_cast(usage), static_cast(mem_type), static_cast(mem_flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *out_memory = reinterpret_cast(new (std::nothrow) wis::DX12Memory(std::move(value))); - if (!*out_memory) + if (!*out_memory) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Memory." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12ResourceAllocatorPlaceBuffer(DX12ResourceAllocator self, DX12Memory memory, uint64_t memory_offset, uint64_t size, WisBufferUsage usage, DX12Buffer* buffer) @@ -314,12 +393,14 @@ extern "C" WisResult DX12ResourceAllocatorPlaceBuffer(DX12ResourceAllocator self auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->PlaceBuffer(*reinterpret_cast(memory), memory_offset, size, static_cast(usage)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *buffer = reinterpret_cast(new (std::nothrow) wis::DX12Buffer(std::move(value))); - if (!*buffer) + if (!*buffer) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Buffer." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12ResourceAllocatorPlaceTexture(DX12ResourceAllocator self, DX12Memory memory, uint64_t memory_offset, const WisTextureDesc* desc, DX12Texture* texture) @@ -327,12 +408,14 @@ extern "C" WisResult DX12ResourceAllocatorPlaceTexture(DX12ResourceAllocator sel auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->PlaceTexture(*reinterpret_cast(memory), memory_offset, *reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *texture = reinterpret_cast(new (std::nothrow) wis::DX12Texture(std::move(value))); - if (!*texture) + if (!*texture) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Texture." }; + } return reinterpret_cast(res); } @@ -410,10 +493,10 @@ extern "C" void DX12CommandListSetPipelineState(DX12CommandList self, DX12Pipeli auto* xself = reinterpret_cast(self); xself->SetPipelineState(*reinterpret_cast(pipeline)); } -extern "C" void DX12CommandListCopyBuffer(DX12CommandList self, DX12Buffer source, DX12Buffer destination, WisBufferRegion region) +extern "C" void DX12CommandListCopyBuffer(DX12CommandList self, DX12Buffer source, DX12Buffer destination, const WisBufferRegion* region) { auto* xself = reinterpret_cast(self); - xself->CopyBuffer(*reinterpret_cast(source), *reinterpret_cast(destination), reinterpret_cast(region)); + xself->CopyBuffer(*reinterpret_cast(source), *reinterpret_cast(destination), *reinterpret_cast(region)); } extern "C" void DX12CommandListCopyBufferToTexture(DX12CommandList self, DX12Buffer source, DX12Texture destination, const WisBufferTextureCopyRegion* regions, uint32_t region_count) { @@ -425,20 +508,20 @@ extern "C" void DX12CommandListCopyTextureToBuffer(DX12CommandList self, DX12Tex auto* xself = reinterpret_cast(self); xself->CopyTextureToBuffer(*reinterpret_cast(source), *reinterpret_cast(destination), reinterpret_cast(regions), region_count); } -extern "C" void DX12CommandListBufferBarrier(DX12CommandList self, WisBufferBarrier barrier, DX12Buffer buffer) +extern "C" void DX12CommandListBufferBarrier(DX12CommandList self, const WisBufferBarrier* barrier, DX12Buffer buffer) { auto* xself = reinterpret_cast(self); - xself->BufferBarrier(reinterpret_cast(barrier), *reinterpret_cast(buffer)); + xself->BufferBarrier(*reinterpret_cast(barrier), *reinterpret_cast(buffer)); } extern "C" void DX12CommandListBufferBarriers(DX12CommandList self, const DX12BufferBarrier2* barriers, uint32_t barrier_count) { auto* xself = reinterpret_cast(self); xself->BufferBarriers(reinterpret_cast(barriers), barrier_count); } -extern "C" void DX12CommandListTextureBarrier(DX12CommandList self, WisTextureBarrier barrier, DX12Texture texture) +extern "C" void DX12CommandListTextureBarrier(DX12CommandList self, const WisTextureBarrier* barrier, DX12Texture texture) { auto* xself = reinterpret_cast(self); - xself->TextureBarrier(reinterpret_cast(barrier), *reinterpret_cast(texture)); + xself->TextureBarrier(*reinterpret_cast(barrier), *reinterpret_cast(texture)); } extern "C" void DX12CommandListTextureBarriers(DX12CommandList self, const DX12TextureBarrier2* barriers, uint32_t barrier_count) { @@ -480,20 +563,20 @@ extern "C" void DX12CommandListIASetIndexBuffer2(DX12CommandList self, DX12Buffe auto* xself = reinterpret_cast(self); xself->IASetIndexBuffer2(*reinterpret_cast(buffer), static_cast(type), size, offset); } -extern "C" void DX12CommandListRSSetViewport(DX12CommandList self, WisViewport viewport) +extern "C" void DX12CommandListRSSetViewport(DX12CommandList self, const WisViewport* viewport) { auto* xself = reinterpret_cast(self); - xself->RSSetViewport(reinterpret_cast(viewport)); + xself->RSSetViewport(*reinterpret_cast(viewport)); } extern "C" void DX12CommandListRSSetViewports(DX12CommandList self, const WisViewport* viewports, uint32_t count) { auto* xself = reinterpret_cast(self); xself->RSSetViewports(reinterpret_cast(viewports), count); } -extern "C" void DX12CommandListRSSetScissor(DX12CommandList self, WisScissor scissor) +extern "C" void DX12CommandListRSSetScissor(DX12CommandList self, const WisScissor* scissor) { auto* xself = reinterpret_cast(self); - xself->RSSetScissor(reinterpret_cast(scissor)); + xself->RSSetScissor(*reinterpret_cast(scissor)); } extern "C" void DX12CommandListRSSetScissors(DX12CommandList self, const WisScissor* scissors, uint32_t count) { @@ -732,12 +815,14 @@ extern "C" WisResult VKFactoryGetAdapter(VKFactory self, uint32_t index, WisAdap auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->GetAdapter(index, static_cast(preference)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *adapter = reinterpret_cast(new (std::nothrow) wis::VKAdapter(std::move(value))); - if (!*adapter) + if (!*adapter) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKAdapter." }; + } return reinterpret_cast(res); } @@ -775,12 +860,14 @@ extern "C" WisResult VKDeviceCreateFence(VKDevice self, uint64_t initial_value, auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateFence(initial_value, static_cast(flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *fence = reinterpret_cast(new (std::nothrow) wis::VKFence(std::move(value))); - if (!*fence) + if (!*fence) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKFence." }; + } return reinterpret_cast(res); } extern "C" WisResult VKDeviceCreateCommandQueue(VKDevice self, WisQueueType type, VKCommandQueue* queue) @@ -788,12 +875,14 @@ extern "C" WisResult VKDeviceCreateCommandQueue(VKDevice self, WisQueueType type auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateCommandQueue(static_cast(type)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *queue = reinterpret_cast(new (std::nothrow) wis::VKCommandQueue(std::move(value))); - if (!*queue) + if (!*queue) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKCommandQueue." }; + } return reinterpret_cast(res); } extern "C" WisResult VKDeviceCreateCommandList(VKDevice self, WisQueueType type, VKCommandList* list) @@ -801,25 +890,29 @@ extern "C" WisResult VKDeviceCreateCommandList(VKDevice self, WisQueueType type, auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateCommandList(static_cast(type)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *list = reinterpret_cast(new (std::nothrow) wis::VKCommandList(std::move(value))); - if (!*list) + if (!*list) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKCommandList." }; + } return reinterpret_cast(res); } extern "C" WisResult VKDeviceCreateGraphicsPipeline(VKDevice self, const VKGraphicsPipelineDesc* desc, VKPipelineState* pipeline) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateGraphicsPipeline(reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateGraphicsPipeline(*reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *pipeline = reinterpret_cast(new (std::nothrow) wis::VKPipelineState(std::move(value))); - if (!*pipeline) + if (!*pipeline) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKPipelineState." }; + } return reinterpret_cast(res); } extern "C" WisResult VKDeviceCreateRootSignature(VKDevice self, const WisPushConstant* push_constants, uint32_t constants_count, const WisPushDescriptor* push_descriptors, uint32_t descriptors_count, uint32_t space_overlap_count, VKRootSignature* signature) @@ -827,12 +920,14 @@ extern "C" WisResult VKDeviceCreateRootSignature(VKDevice self, const WisPushCon auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateRootSignature(reinterpret_cast(push_constants), constants_count, reinterpret_cast(push_descriptors), descriptors_count, space_overlap_count); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *signature = reinterpret_cast(new (std::nothrow) wis::VKRootSignature(std::move(value))); - if (!*signature) + if (!*signature) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKRootSignature." }; + } return reinterpret_cast(res); } extern "C" WisResult VKDeviceCreateRootSignature2(VKDevice self, const WisPushConstant* push_constants, uint32_t constants_count, const WisPushDescriptor* push_descriptors, uint32_t push_descriptors_count, const WisDescriptorSpacing* descriptor_spacing, VKRootSignature* signature) @@ -840,12 +935,14 @@ extern "C" WisResult VKDeviceCreateRootSignature2(VKDevice self, const WisPushCo auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateRootSignature2(reinterpret_cast(push_constants), constants_count, reinterpret_cast(push_descriptors), push_descriptors_count, reinterpret_cast(descriptor_spacing)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *signature = reinterpret_cast(new (std::nothrow) wis::VKRootSignature(std::move(value))); - if (!*signature) + if (!*signature) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKRootSignature." }; + } return reinterpret_cast(res); } extern "C" WisResult VKDeviceCreateShader(VKDevice self, void* data, uint32_t size, VKShader* shader) @@ -853,12 +950,14 @@ extern "C" WisResult VKDeviceCreateShader(VKDevice self, void* data, uint32_t si auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateShader(data, size); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *shader = reinterpret_cast(new (std::nothrow) wis::VKShader(std::move(value))); - if (!*shader) + if (!*shader) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKShader." }; + } return reinterpret_cast(res); } extern "C" WisResult VKDeviceCreateAllocator(VKDevice self, VKResourceAllocator* allocator) @@ -866,64 +965,89 @@ extern "C" WisResult VKDeviceCreateAllocator(VKDevice self, VKResourceAllocator* auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateAllocator(); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *allocator = reinterpret_cast(new (std::nothrow) wis::VKResourceAllocator(std::move(value))); - if (!*allocator) + if (!*allocator) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKResourceAllocator." }; + } return reinterpret_cast(res); } -extern "C" WisResult VKDeviceCreateRenderTarget(VKDevice self, VKTexture texture, WisRenderTargetDesc desc, VKRenderTarget* target) +extern "C" WisResult VKDeviceCreateRenderTarget(VKDevice self, VKTexture texture, const WisRenderTargetDesc* desc, VKRenderTarget* target) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateRenderTarget(*reinterpret_cast(texture), reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateRenderTarget(*reinterpret_cast(texture), *reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *target = reinterpret_cast(new (std::nothrow) wis::VKRenderTarget(std::move(value))); - if (!*target) + if (!*target) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKRenderTarget." }; + } return reinterpret_cast(res); } -extern "C" WisResult VKDeviceCreateDepthStencilTarget(VKDevice self, VKTexture texture, WisRenderTargetDesc desc, VKRenderTarget* target) +extern "C" WisResult VKDeviceCreateDepthStencilTarget(VKDevice self, VKTexture texture, const WisRenderTargetDesc* desc, VKRenderTarget* target) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateDepthStencilTarget(*reinterpret_cast(texture), reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateDepthStencilTarget(*reinterpret_cast(texture), *reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *target = reinterpret_cast(new (std::nothrow) wis::VKRenderTarget(std::move(value))); - if (!*target) + if (!*target) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKRenderTarget." }; + } return reinterpret_cast(res); } extern "C" WisResult VKDeviceCreateSampler(VKDevice self, const WisSamplerDesc* desc, VKSampler* sampler) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateSampler(reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateSampler(*reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *sampler = reinterpret_cast(new (std::nothrow) wis::VKSampler(std::move(value))); - if (!*sampler) + if (!*sampler) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKSampler." }; + } return reinterpret_cast(res); } -extern "C" WisResult VKDeviceCreateShaderResource(VKDevice self, VKTexture texture, WisShaderResourceDesc desc, VKShaderResource* resource) +extern "C" WisResult VKDeviceCreateShaderResource(VKDevice self, VKTexture texture, const WisShaderResourceDesc* desc, VKShaderResource* resource) { auto* xself = reinterpret_cast(self); - auto&& [res, value] = xself->CreateShaderResource(*reinterpret_cast(texture), reinterpret_cast(desc)); + auto&& [res, value] = xself->CreateShaderResource(*reinterpret_cast(texture), *reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *resource = reinterpret_cast(new (std::nothrow) wis::VKShaderResource(std::move(value))); - if (!*resource) + if (!*resource) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKShaderResource." }; + } + return reinterpret_cast(res); +} +extern "C" WisResult VKDeviceCreateDescriptorStorage(VKDevice self, const WisDescriptorStorageDesc* desc, VKDescriptorStorage* storage) +{ + auto* xself = reinterpret_cast(self); + auto&& [res, value] = xself->CreateDescriptorStorage(*reinterpret_cast(desc)); + + if (res.status != wis::Status::Ok) { + return reinterpret_cast(res); + } + + *storage = reinterpret_cast(new (std::nothrow) wis::VKDescriptorStorage(std::move(value))); + if (!*storage) { + return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKDescriptorStorage." }; + } return reinterpret_cast(res); } extern "C" bool VKDeviceQueryFeatureSupport(VKDevice self, WisDeviceFeature feature) @@ -945,12 +1069,14 @@ extern "C" WisResult VKResourceAllocatorCreateBuffer(VKResourceAllocator self, u auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateBuffer(size, static_cast(usage), static_cast(memory), static_cast(mem_flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *buffer = reinterpret_cast(new (std::nothrow) wis::VKBuffer(std::move(value))); - if (!*buffer) + if (!*buffer) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKBuffer." }; + } return reinterpret_cast(res); } extern "C" WisResult VKResourceAllocatorCreateTexture(VKResourceAllocator self, const WisTextureDesc* desc, WisMemoryType memory, WisMemoryFlags mem_flags, VKTexture* texture) @@ -958,12 +1084,44 @@ extern "C" WisResult VKResourceAllocatorCreateTexture(VKResourceAllocator self, auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateTexture(*reinterpret_cast(desc), static_cast(memory), static_cast(mem_flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *texture = reinterpret_cast(new (std::nothrow) wis::VKTexture(std::move(value))); - if (!*texture) + if (!*texture) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKTexture." }; + } + return reinterpret_cast(res); +} +extern "C" WisResult VKResourceAllocatorCreateUploadBuffer(VKResourceAllocator self, uint64_t size, VKBuffer* buffer) +{ + auto* xself = reinterpret_cast(self); + auto&& [res, value] = xself->CreateUploadBuffer(size); + + if (res.status != wis::Status::Ok) { + return reinterpret_cast(res); + } + + *buffer = reinterpret_cast(new (std::nothrow) wis::VKBuffer(std::move(value))); + if (!*buffer) { + return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKBuffer." }; + } + return reinterpret_cast(res); +} +extern "C" WisResult VKResourceAllocatorCreateReadbackBuffer(VKResourceAllocator self, uint64_t size, VKBuffer* buffer) +{ + auto* xself = reinterpret_cast(self); + auto&& [res, value] = xself->CreateReadbackBuffer(size); + + if (res.status != wis::Status::Ok) { + return reinterpret_cast(res); + } + + *buffer = reinterpret_cast(new (std::nothrow) wis::VKBuffer(std::move(value))); + if (!*buffer) { + return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKBuffer." }; + } return reinterpret_cast(res); } extern "C" WisAllocationInfo VKResourceAllocatorGetTextureAllocationInfo(VKResourceAllocator self, const WisTextureDesc* desc) @@ -985,12 +1143,14 @@ extern "C" WisResult VKResourceAllocatorAllocateTextureMemory(VKResourceAllocato auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->AllocateTextureMemory(size, static_cast(usage), static_cast(mem_type), static_cast(mem_flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *out_memory = reinterpret_cast(new (std::nothrow) wis::VKMemory(std::move(value))); - if (!*out_memory) + if (!*out_memory) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKMemory." }; + } return reinterpret_cast(res); } extern "C" WisResult VKResourceAllocatorAllocateBufferMemory(VKResourceAllocator self, uint64_t size, WisBufferUsage usage, WisMemoryType mem_type, WisMemoryFlags mem_flags, VKMemory* out_memory) @@ -998,12 +1158,14 @@ extern "C" WisResult VKResourceAllocatorAllocateBufferMemory(VKResourceAllocator auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->AllocateBufferMemory(size, static_cast(usage), static_cast(mem_type), static_cast(mem_flags)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *out_memory = reinterpret_cast(new (std::nothrow) wis::VKMemory(std::move(value))); - if (!*out_memory) + if (!*out_memory) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKMemory." }; + } return reinterpret_cast(res); } extern "C" WisResult VKResourceAllocatorPlaceBuffer(VKResourceAllocator self, VKMemory memory, uint64_t memory_offset, uint64_t size, WisBufferUsage usage, VKBuffer* buffer) @@ -1011,12 +1173,14 @@ extern "C" WisResult VKResourceAllocatorPlaceBuffer(VKResourceAllocator self, VK auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->PlaceBuffer(*reinterpret_cast(memory), memory_offset, size, static_cast(usage)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *buffer = reinterpret_cast(new (std::nothrow) wis::VKBuffer(std::move(value))); - if (!*buffer) + if (!*buffer) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKBuffer." }; + } return reinterpret_cast(res); } extern "C" WisResult VKResourceAllocatorPlaceTexture(VKResourceAllocator self, VKMemory memory, uint64_t memory_offset, const WisTextureDesc* desc, VKTexture* texture) @@ -1024,12 +1188,14 @@ extern "C" WisResult VKResourceAllocatorPlaceTexture(VKResourceAllocator self, V auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->PlaceTexture(*reinterpret_cast(memory), memory_offset, *reinterpret_cast(desc)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *texture = reinterpret_cast(new (std::nothrow) wis::VKTexture(std::move(value))); - if (!*texture) + if (!*texture) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKTexture." }; + } return reinterpret_cast(res); } @@ -1107,10 +1273,10 @@ extern "C" void VKCommandListSetPipelineState(VKCommandList self, VKPipelineStat auto* xself = reinterpret_cast(self); xself->SetPipelineState(*reinterpret_cast(pipeline)); } -extern "C" void VKCommandListCopyBuffer(VKCommandList self, VKBuffer source, VKBuffer destination, WisBufferRegion region) +extern "C" void VKCommandListCopyBuffer(VKCommandList self, VKBuffer source, VKBuffer destination, const WisBufferRegion* region) { auto* xself = reinterpret_cast(self); - xself->CopyBuffer(*reinterpret_cast(source), *reinterpret_cast(destination), reinterpret_cast(region)); + xself->CopyBuffer(*reinterpret_cast(source), *reinterpret_cast(destination), *reinterpret_cast(region)); } extern "C" void VKCommandListCopyBufferToTexture(VKCommandList self, VKBuffer source, VKTexture destination, const WisBufferTextureCopyRegion* regions, uint32_t region_count) { @@ -1122,20 +1288,20 @@ extern "C" void VKCommandListCopyTextureToBuffer(VKCommandList self, VKTexture s auto* xself = reinterpret_cast(self); xself->CopyTextureToBuffer(*reinterpret_cast(source), *reinterpret_cast(destination), reinterpret_cast(regions), region_count); } -extern "C" void VKCommandListBufferBarrier(VKCommandList self, WisBufferBarrier barrier, VKBuffer buffer) +extern "C" void VKCommandListBufferBarrier(VKCommandList self, const WisBufferBarrier* barrier, VKBuffer buffer) { auto* xself = reinterpret_cast(self); - xself->BufferBarrier(reinterpret_cast(barrier), *reinterpret_cast(buffer)); + xself->BufferBarrier(*reinterpret_cast(barrier), *reinterpret_cast(buffer)); } extern "C" void VKCommandListBufferBarriers(VKCommandList self, const VKBufferBarrier2* barriers, uint32_t barrier_count) { auto* xself = reinterpret_cast(self); xself->BufferBarriers(reinterpret_cast(barriers), barrier_count); } -extern "C" void VKCommandListTextureBarrier(VKCommandList self, WisTextureBarrier barrier, VKTexture texture) +extern "C" void VKCommandListTextureBarrier(VKCommandList self, const WisTextureBarrier* barrier, VKTexture texture) { auto* xself = reinterpret_cast(self); - xself->TextureBarrier(reinterpret_cast(barrier), *reinterpret_cast(texture)); + xself->TextureBarrier(*reinterpret_cast(barrier), *reinterpret_cast(texture)); } extern "C" void VKCommandListTextureBarriers(VKCommandList self, const VKTextureBarrier2* barriers, uint32_t barrier_count) { @@ -1177,20 +1343,20 @@ extern "C" void VKCommandListIASetIndexBuffer2(VKCommandList self, VKBuffer buff auto* xself = reinterpret_cast(self); xself->IASetIndexBuffer2(*reinterpret_cast(buffer), static_cast(type), size, offset); } -extern "C" void VKCommandListRSSetViewport(VKCommandList self, WisViewport viewport) +extern "C" void VKCommandListRSSetViewport(VKCommandList self, const WisViewport* viewport) { auto* xself = reinterpret_cast(self); - xself->RSSetViewport(reinterpret_cast(viewport)); + xself->RSSetViewport(*reinterpret_cast(viewport)); } extern "C" void VKCommandListRSSetViewports(VKCommandList self, const WisViewport* viewports, uint32_t count) { auto* xself = reinterpret_cast(self); xself->RSSetViewports(reinterpret_cast(viewports), count); } -extern "C" void VKCommandListRSSetScissor(VKCommandList self, WisScissor scissor) +extern "C" void VKCommandListRSSetScissor(VKCommandList self, const WisScissor* scissor) { auto* xself = reinterpret_cast(self); - xself->RSSetScissor(reinterpret_cast(scissor)); + xself->RSSetScissor(*reinterpret_cast(scissor)); } extern "C" void VKCommandListRSSetScissors(VKCommandList self, const WisScissor* scissors, uint32_t count) { diff --git a/bindings/wisdom.h b/bindings/wisdom.h index 6441a023..02d012b5 100644 --- a/bindings/wisdom.h +++ b/bindings/wisdom.h @@ -6,7 +6,7 @@ /** \mainpage Wisdom API Documentation -Version 0.4.0 +Version 0.5.0 Copyright (c) 2024 Ilya Doroshenko. All rights reserved. License: MIT @@ -1172,6 +1172,7 @@ enum WisFactoryExtID { enum WisDeviceExtID { DeviceExtIDCustom = 0, ///< Custom provided extension. Default initialization of the extension is done by user. DeviceExtIDDescriptorBufferExtension = 1, + DeviceExtIDExtendedAllocation = 2, }; //------------------------------------------------------------------------- @@ -2307,7 +2308,7 @@ WISDOM_API WisResult VKDeviceCreateAllocator(VKDevice self, VKResourceAllocator* * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -WISDOM_API WisResult VKDeviceCreateRenderTarget(VKDevice self, VKTexture texture, WisRenderTargetDesc desc, VKRenderTarget* target); +WISDOM_API WisResult VKDeviceCreateRenderTarget(VKDevice self, VKTexture texture, const WisRenderTargetDesc* desc, VKRenderTarget* target); /** * @brief Creates a depth stencil target object. @@ -2321,7 +2322,7 @@ WISDOM_API WisResult VKDeviceCreateRenderTarget(VKDevice self, VKTexture texture * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -WISDOM_API WisResult VKDeviceCreateDepthStencilTarget(VKDevice self, VKTexture texture, WisRenderTargetDesc desc, VKRenderTarget* target); +WISDOM_API WisResult VKDeviceCreateDepthStencilTarget(VKDevice self, VKTexture texture, const WisRenderTargetDesc* desc, VKRenderTarget* target); /** * @brief Creates a sampler object. @@ -2342,7 +2343,18 @@ WISDOM_API WisResult VKDeviceCreateSampler(VKDevice self, const WisSamplerDesc* * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -WISDOM_API WisResult VKDeviceCreateShaderResource(VKDevice self, VKTexture texture, WisShaderResourceDesc desc, VKShaderResource* resource); +WISDOM_API WisResult VKDeviceCreateShaderResource(VKDevice self, VKTexture texture, const WisShaderResourceDesc* desc, VKShaderResource* resource); + +/** + * @brief Creates a descriptor storage object with specified number of bindings to allocate. + * Switching between several DescriptorStorage is slow, consider allocating one big set and copy descriptors to it. + * @param self valid handle to the Device + * @param desc The description of the descriptor storage to create. + * @param storage VKDescriptorStorage on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +WISDOM_API WisResult VKDeviceCreateDescriptorStorage(VKDevice self, const WisDescriptorStorageDesc* desc, VKDescriptorStorage* storage); /** * @brief Queries if the device supports the feature. @@ -2387,6 +2399,28 @@ WISDOM_API WisResult VKResourceAllocatorCreateBuffer(VKResourceAllocator self, u * */ WISDOM_API WisResult VKResourceAllocatorCreateTexture(VKResourceAllocator self, const WisTextureDesc* desc, WisMemoryType memory, WisMemoryFlags mem_flags, VKTexture* texture); +/** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param self valid handle to the ResourceAllocator + * @param size The size of the buffer in bytes. + * @param buffer VKBuffer on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +WISDOM_API WisResult VKResourceAllocatorCreateUploadBuffer(VKResourceAllocator self, uint64_t size, VKBuffer* buffer); + +/** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param self valid handle to the ResourceAllocator + * @param size The size of the buffer in bytes. + * @param buffer VKBuffer on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +WISDOM_API WisResult VKResourceAllocatorCreateReadbackBuffer(VKResourceAllocator self, uint64_t size, VKBuffer* buffer); + /** * @brief Returns the allocation info for the texture. * @param self valid handle to the ResourceAllocator @@ -2544,7 +2578,7 @@ WISDOM_API void VKCommandListSetPipelineState(VKCommandList self, VKPipelineStat * @param destination The destination buffer to copy to. * @param region The region to copy. * */ -WISDOM_API void VKCommandListCopyBuffer(VKCommandList self, VKBuffer source, VKBuffer destination, WisBufferRegion region); +WISDOM_API void VKCommandListCopyBuffer(VKCommandList self, VKBuffer source, VKBuffer destination, const WisBufferRegion* region); /** * @brief Copies data from buffer to texture. @@ -2572,7 +2606,7 @@ WISDOM_API void VKCommandListCopyTextureToBuffer(VKCommandList self, VKTexture s * @param barrier The barrier to set. * @param buffer The buffer to set the barrier on. * */ -WISDOM_API void VKCommandListBufferBarrier(VKCommandList self, WisBufferBarrier barrier, VKBuffer buffer); +WISDOM_API void VKCommandListBufferBarrier(VKCommandList self, const WisBufferBarrier* barrier, VKBuffer buffer); /** * @brief Sets the barriers on the buffers. You may set up to 8 buffer barriers for max efficiency. @@ -2588,7 +2622,7 @@ WISDOM_API void VKCommandListBufferBarriers(VKCommandList self, const VKBufferBa * @param barrier The barrier to set. * @param texture The texture to set the barrier on. * */ -WISDOM_API void VKCommandListTextureBarrier(VKCommandList self, WisTextureBarrier barrier, VKTexture texture); +WISDOM_API void VKCommandListTextureBarrier(VKCommandList self, const WisTextureBarrier* barrier, VKTexture texture); /** * @brief Sets the barriers on the textures. You may set up to 8 texture barriers for max efficiency. @@ -2660,7 +2694,7 @@ WISDOM_API void VKCommandListIASetIndexBuffer2(VKCommandList self, VKBuffer buff * @param self valid handle to the CommandList * @param viewport The viewport to set. * */ -WISDOM_API void VKCommandListRSSetViewport(VKCommandList self, WisViewport viewport); +WISDOM_API void VKCommandListRSSetViewport(VKCommandList self, const WisViewport* viewport); /** * @brief Sets multiple viewports. @@ -2675,7 +2709,7 @@ WISDOM_API void VKCommandListRSSetViewports(VKCommandList self, const WisViewpor * @param self valid handle to the CommandList * @param scissor The scissor to set. * */ -WISDOM_API void VKCommandListRSSetScissor(VKCommandList self, WisScissor scissor); +WISDOM_API void VKCommandListRSSetScissor(VKCommandList self, const WisScissor* scissor); /** * @brief Sets multiple scissor rects. @@ -3314,7 +3348,7 @@ WISDOM_API WisResult DX12DeviceCreateAllocator(DX12Device self, DX12ResourceAllo * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -WISDOM_API WisResult DX12DeviceCreateRenderTarget(DX12Device self, DX12Texture texture, WisRenderTargetDesc desc, DX12RenderTarget* target); +WISDOM_API WisResult DX12DeviceCreateRenderTarget(DX12Device self, DX12Texture texture, const WisRenderTargetDesc* desc, DX12RenderTarget* target); /** * @brief Creates a depth stencil target object. @@ -3328,7 +3362,7 @@ WISDOM_API WisResult DX12DeviceCreateRenderTarget(DX12Device self, DX12Texture t * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -WISDOM_API WisResult DX12DeviceCreateDepthStencilTarget(DX12Device self, DX12Texture texture, WisRenderTargetDesc desc, DX12RenderTarget* target); +WISDOM_API WisResult DX12DeviceCreateDepthStencilTarget(DX12Device self, DX12Texture texture, const WisRenderTargetDesc* desc, DX12RenderTarget* target); /** * @brief Creates a sampler object. @@ -3349,7 +3383,18 @@ WISDOM_API WisResult DX12DeviceCreateSampler(DX12Device self, const WisSamplerDe * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -WISDOM_API WisResult DX12DeviceCreateShaderResource(DX12Device self, DX12Texture texture, WisShaderResourceDesc desc, DX12ShaderResource* resource); +WISDOM_API WisResult DX12DeviceCreateShaderResource(DX12Device self, DX12Texture texture, const WisShaderResourceDesc* desc, DX12ShaderResource* resource); + +/** + * @brief Creates a descriptor storage object with specified number of bindings to allocate. + * Switching between several DescriptorStorage is slow, consider allocating one big set and copy descriptors to it. + * @param self valid handle to the Device + * @param desc The description of the descriptor storage to create. + * @param storage DX12DescriptorStorage on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +WISDOM_API WisResult DX12DeviceCreateDescriptorStorage(DX12Device self, const WisDescriptorStorageDesc* desc, DX12DescriptorStorage* storage); /** * @brief Queries if the device supports the feature. @@ -3394,6 +3439,28 @@ WISDOM_API WisResult DX12ResourceAllocatorCreateBuffer(DX12ResourceAllocator sel * */ WISDOM_API WisResult DX12ResourceAllocatorCreateTexture(DX12ResourceAllocator self, const WisTextureDesc* desc, WisMemoryType memory, WisMemoryFlags mem_flags, DX12Texture* texture); +/** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param self valid handle to the ResourceAllocator + * @param size The size of the buffer in bytes. + * @param buffer DX12Buffer on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +WISDOM_API WisResult DX12ResourceAllocatorCreateUploadBuffer(DX12ResourceAllocator self, uint64_t size, DX12Buffer* buffer); + +/** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param self valid handle to the ResourceAllocator + * @param size The size of the buffer in bytes. + * @param buffer DX12Buffer on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +WISDOM_API WisResult DX12ResourceAllocatorCreateReadbackBuffer(DX12ResourceAllocator self, uint64_t size, DX12Buffer* buffer); + /** * @brief Returns the allocation info for the texture. * @param self valid handle to the ResourceAllocator @@ -3551,7 +3618,7 @@ WISDOM_API void DX12CommandListSetPipelineState(DX12CommandList self, DX12Pipeli * @param destination The destination buffer to copy to. * @param region The region to copy. * */ -WISDOM_API void DX12CommandListCopyBuffer(DX12CommandList self, DX12Buffer source, DX12Buffer destination, WisBufferRegion region); +WISDOM_API void DX12CommandListCopyBuffer(DX12CommandList self, DX12Buffer source, DX12Buffer destination, const WisBufferRegion* region); /** * @brief Copies data from buffer to texture. @@ -3579,7 +3646,7 @@ WISDOM_API void DX12CommandListCopyTextureToBuffer(DX12CommandList self, DX12Tex * @param barrier The barrier to set. * @param buffer The buffer to set the barrier on. * */ -WISDOM_API void DX12CommandListBufferBarrier(DX12CommandList self, WisBufferBarrier barrier, DX12Buffer buffer); +WISDOM_API void DX12CommandListBufferBarrier(DX12CommandList self, const WisBufferBarrier* barrier, DX12Buffer buffer); /** * @brief Sets the barriers on the buffers. You may set up to 8 buffer barriers for max efficiency. @@ -3595,7 +3662,7 @@ WISDOM_API void DX12CommandListBufferBarriers(DX12CommandList self, const DX12Bu * @param barrier The barrier to set. * @param texture The texture to set the barrier on. * */ -WISDOM_API void DX12CommandListTextureBarrier(DX12CommandList self, WisTextureBarrier barrier, DX12Texture texture); +WISDOM_API void DX12CommandListTextureBarrier(DX12CommandList self, const WisTextureBarrier* barrier, DX12Texture texture); /** * @brief Sets the barriers on the textures. You may set up to 8 texture barriers for max efficiency. @@ -3667,7 +3734,7 @@ WISDOM_API void DX12CommandListIASetIndexBuffer2(DX12CommandList self, DX12Buffe * @param self valid handle to the CommandList * @param viewport The viewport to set. * */ -WISDOM_API void DX12CommandListRSSetViewport(DX12CommandList self, WisViewport viewport); +WISDOM_API void DX12CommandListRSSetViewport(DX12CommandList self, const WisViewport* viewport); /** * @brief Sets multiple viewports. @@ -3682,7 +3749,7 @@ WISDOM_API void DX12CommandListRSSetViewports(DX12CommandList self, const WisVie * @param self valid handle to the CommandList * @param scissor The scissor to set. * */ -WISDOM_API void DX12CommandListRSSetScissor(DX12CommandList self, WisScissor scissor); +WISDOM_API void DX12CommandListRSSetScissor(DX12CommandList self, const WisScissor* scissor); /** * @brief Sets multiple scissor rects. @@ -4252,7 +4319,7 @@ inline WisResult WisDeviceCreateAllocator(WisDevice self, WisResourceAllocator* * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -inline WisResult WisDeviceCreateRenderTarget(WisDevice self, WisTexture texture, WisRenderTargetDesc desc, WisRenderTarget* target) +inline WisResult WisDeviceCreateRenderTarget(WisDevice self, WisTexture texture, const WisRenderTargetDesc* desc, WisRenderTarget* target) { return DX12DeviceCreateRenderTarget(self, texture, desc, target); } @@ -4269,7 +4336,7 @@ inline WisResult WisDeviceCreateRenderTarget(WisDevice self, WisTexture texture, * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -inline WisResult WisDeviceCreateDepthStencilTarget(WisDevice self, WisTexture texture, WisRenderTargetDesc desc, WisRenderTarget* target) +inline WisResult WisDeviceCreateDepthStencilTarget(WisDevice self, WisTexture texture, const WisRenderTargetDesc* desc, WisRenderTarget* target) { return DX12DeviceCreateDepthStencilTarget(self, texture, desc, target); } @@ -4296,11 +4363,25 @@ inline WisResult WisDeviceCreateSampler(WisDevice self, const WisSamplerDesc* de * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -inline WisResult WisDeviceCreateShaderResource(WisDevice self, WisTexture texture, WisShaderResourceDesc desc, WisShaderResource* resource) +inline WisResult WisDeviceCreateShaderResource(WisDevice self, WisTexture texture, const WisShaderResourceDesc* desc, WisShaderResource* resource) { return DX12DeviceCreateShaderResource(self, texture, desc, resource); } +/** + * @brief Creates a descriptor storage object with specified number of bindings to allocate. + * Switching between several DescriptorStorage is slow, consider allocating one big set and copy descriptors to it. + * @param self valid handle to the Device + * @param desc The description of the descriptor storage to create. + * @param storage WisDescriptorStorage on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +inline WisResult WisDeviceCreateDescriptorStorage(WisDevice self, const WisDescriptorStorageDesc* desc, WisDescriptorStorage* storage) +{ + return DX12DeviceCreateDescriptorStorage(self, desc, storage); +} + /** * @brief Queries if the device supports the feature. * @param self valid handle to the Device @@ -4356,6 +4437,34 @@ inline WisResult WisResourceAllocatorCreateTexture(WisResourceAllocator self, co return DX12ResourceAllocatorCreateTexture(self, desc, memory, mem_flags, texture); } +/** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param self valid handle to the ResourceAllocator + * @param size The size of the buffer in bytes. + * @param buffer WisBuffer on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +inline WisResult WisResourceAllocatorCreateUploadBuffer(WisResourceAllocator self, uint64_t size, WisBuffer* buffer) +{ + return DX12ResourceAllocatorCreateUploadBuffer(self, size, buffer); +} + +/** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param self valid handle to the ResourceAllocator + * @param size The size of the buffer in bytes. + * @param buffer WisBuffer on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +inline WisResult WisResourceAllocatorCreateReadbackBuffer(WisResourceAllocator self, uint64_t size, WisBuffer* buffer) +{ + return DX12ResourceAllocatorCreateReadbackBuffer(self, size, buffer); +} + /** * @brief Returns the allocation info for the texture. * @param self valid handle to the ResourceAllocator @@ -4564,7 +4673,7 @@ inline void WisCommandListSetPipelineState(WisCommandList self, WisPipelineState * @param destination The destination buffer to copy to. * @param region The region to copy. * */ -inline void WisCommandListCopyBuffer(WisCommandList self, WisBuffer source, WisBuffer destination, WisBufferRegion region) +inline void WisCommandListCopyBuffer(WisCommandList self, WisBuffer source, WisBuffer destination, const WisBufferRegion* region) { DX12CommandListCopyBuffer(self, source, destination, region); } @@ -4601,7 +4710,7 @@ inline void WisCommandListCopyTextureToBuffer(WisCommandList self, WisTexture so * @param barrier The barrier to set. * @param buffer The buffer to set the barrier on. * */ -inline void WisCommandListBufferBarrier(WisCommandList self, WisBufferBarrier barrier, WisBuffer buffer) +inline void WisCommandListBufferBarrier(WisCommandList self, const WisBufferBarrier* barrier, WisBuffer buffer) { DX12CommandListBufferBarrier(self, barrier, buffer); } @@ -4623,7 +4732,7 @@ inline void WisCommandListBufferBarriers(WisCommandList self, const WisBufferBar * @param barrier The barrier to set. * @param texture The texture to set the barrier on. * */ -inline void WisCommandListTextureBarrier(WisCommandList self, WisTextureBarrier barrier, WisTexture texture) +inline void WisCommandListTextureBarrier(WisCommandList self, const WisTextureBarrier* barrier, WisTexture texture) { DX12CommandListTextureBarrier(self, barrier, texture); } @@ -4722,7 +4831,7 @@ inline void WisCommandListIASetIndexBuffer2(WisCommandList self, WisBuffer buffe * @param self valid handle to the CommandList * @param viewport The viewport to set. * */ -inline void WisCommandListRSSetViewport(WisCommandList self, WisViewport viewport) +inline void WisCommandListRSSetViewport(WisCommandList self, const WisViewport* viewport) { DX12CommandListRSSetViewport(self, viewport); } @@ -4743,7 +4852,7 @@ inline void WisCommandListRSSetViewports(WisCommandList self, const WisViewport* * @param self valid handle to the CommandList * @param scissor The scissor to set. * */ -inline void WisCommandListRSSetScissor(WisCommandList self, WisScissor scissor) +inline void WisCommandListRSSetScissor(WisCommandList self, const WisScissor* scissor) { DX12CommandListRSSetScissor(self, scissor); } @@ -5388,7 +5497,7 @@ inline WisResult WisDeviceCreateAllocator(WisDevice self, WisResourceAllocator* * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -inline WisResult WisDeviceCreateRenderTarget(WisDevice self, WisTexture texture, WisRenderTargetDesc desc, WisRenderTarget* target) +inline WisResult WisDeviceCreateRenderTarget(WisDevice self, WisTexture texture, const WisRenderTargetDesc* desc, WisRenderTarget* target) { return VKDeviceCreateRenderTarget(self, texture, desc, target); } @@ -5405,7 +5514,7 @@ inline WisResult WisDeviceCreateRenderTarget(WisDevice self, WisTexture texture, * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -inline WisResult WisDeviceCreateDepthStencilTarget(WisDevice self, WisTexture texture, WisRenderTargetDesc desc, WisRenderTarget* target) +inline WisResult WisDeviceCreateDepthStencilTarget(WisDevice self, WisTexture texture, const WisRenderTargetDesc* desc, WisRenderTarget* target) { return VKDeviceCreateDepthStencilTarget(self, texture, desc, target); } @@ -5432,11 +5541,25 @@ inline WisResult WisDeviceCreateSampler(WisDevice self, const WisSamplerDesc* de * @return Result with StatusOk on success. * Error in WisResult::error otherwise. * */ -inline WisResult WisDeviceCreateShaderResource(WisDevice self, WisTexture texture, WisShaderResourceDesc desc, WisShaderResource* resource) +inline WisResult WisDeviceCreateShaderResource(WisDevice self, WisTexture texture, const WisShaderResourceDesc* desc, WisShaderResource* resource) { return VKDeviceCreateShaderResource(self, texture, desc, resource); } +/** + * @brief Creates a descriptor storage object with specified number of bindings to allocate. + * Switching between several DescriptorStorage is slow, consider allocating one big set and copy descriptors to it. + * @param self valid handle to the Device + * @param desc The description of the descriptor storage to create. + * @param storage WisDescriptorStorage on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +inline WisResult WisDeviceCreateDescriptorStorage(WisDevice self, const WisDescriptorStorageDesc* desc, WisDescriptorStorage* storage) +{ + return VKDeviceCreateDescriptorStorage(self, desc, storage); +} + /** * @brief Queries if the device supports the feature. * @param self valid handle to the Device @@ -5492,6 +5615,34 @@ inline WisResult WisResourceAllocatorCreateTexture(WisResourceAllocator self, co return VKResourceAllocatorCreateTexture(self, desc, memory, mem_flags, texture); } +/** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param self valid handle to the ResourceAllocator + * @param size The size of the buffer in bytes. + * @param buffer WisBuffer on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +inline WisResult WisResourceAllocatorCreateUploadBuffer(WisResourceAllocator self, uint64_t size, WisBuffer* buffer) +{ + return VKResourceAllocatorCreateUploadBuffer(self, size, buffer); +} + +/** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param self valid handle to the ResourceAllocator + * @param size The size of the buffer in bytes. + * @param buffer WisBuffer on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +inline WisResult WisResourceAllocatorCreateReadbackBuffer(WisResourceAllocator self, uint64_t size, WisBuffer* buffer) +{ + return VKResourceAllocatorCreateReadbackBuffer(self, size, buffer); +} + /** * @brief Returns the allocation info for the texture. * @param self valid handle to the ResourceAllocator @@ -5700,7 +5851,7 @@ inline void WisCommandListSetPipelineState(WisCommandList self, WisPipelineState * @param destination The destination buffer to copy to. * @param region The region to copy. * */ -inline void WisCommandListCopyBuffer(WisCommandList self, WisBuffer source, WisBuffer destination, WisBufferRegion region) +inline void WisCommandListCopyBuffer(WisCommandList self, WisBuffer source, WisBuffer destination, const WisBufferRegion* region) { VKCommandListCopyBuffer(self, source, destination, region); } @@ -5737,7 +5888,7 @@ inline void WisCommandListCopyTextureToBuffer(WisCommandList self, WisTexture so * @param barrier The barrier to set. * @param buffer The buffer to set the barrier on. * */ -inline void WisCommandListBufferBarrier(WisCommandList self, WisBufferBarrier barrier, WisBuffer buffer) +inline void WisCommandListBufferBarrier(WisCommandList self, const WisBufferBarrier* barrier, WisBuffer buffer) { VKCommandListBufferBarrier(self, barrier, buffer); } @@ -5759,7 +5910,7 @@ inline void WisCommandListBufferBarriers(WisCommandList self, const WisBufferBar * @param barrier The barrier to set. * @param texture The texture to set the barrier on. * */ -inline void WisCommandListTextureBarrier(WisCommandList self, WisTextureBarrier barrier, WisTexture texture) +inline void WisCommandListTextureBarrier(WisCommandList self, const WisTextureBarrier* barrier, WisTexture texture) { VKCommandListTextureBarrier(self, barrier, texture); } @@ -5858,7 +6009,7 @@ inline void WisCommandListIASetIndexBuffer2(WisCommandList self, WisBuffer buffe * @param self valid handle to the CommandList * @param viewport The viewport to set. * */ -inline void WisCommandListRSSetViewport(WisCommandList self, WisViewport viewport) +inline void WisCommandListRSSetViewport(WisCommandList self, const WisViewport* viewport) { VKCommandListRSSetViewport(self, viewport); } @@ -5879,7 +6030,7 @@ inline void WisCommandListRSSetViewports(WisCommandList self, const WisViewport* * @param self valid handle to the CommandList * @param scissor The scissor to set. * */ -inline void WisCommandListRSSetScissor(WisCommandList self, WisScissor scissor) +inline void WisCommandListRSSetScissor(WisCommandList self, const WisScissor* scissor) { VKCommandListRSSetScissor(self, scissor); } @@ -6816,6 +6967,190 @@ inline void WisDescriptorBufferWriteConstantBuffer(WisDescriptorBuffer self, uin //------------------------------------------------------------------------- +// ExtendedAllocation-- +#ifndef WIS_ExtendedAllocation +#define WIS_ExtendedAllocation 1 +#endif + +#ifdef WISDOM_VULKAN +typedef VKFactoryExtension VKExtendedAllocation; +// VKExtendedAllocation methods -- +/** + * @brief Creates a texture that is optimized for GPU upload. + * Subsequently this texture may be directly mapped and does not require copying through copy queue. + * The memory behaves as GPU local memory. Requires ReBAR enabled in BIOS. + * @param self valid handle to the ExtendedAllocation + * @param allocator The allocator to create the texture with. + * Allocator must be created by the same device, that initialized this extension. + * @param desc The description of the texture to create. + * @param initial_state The initial state of the texture. Default is Common. + * @param flags The flags of the memory to create the texture with. Default is None. + * @param texture VKTexture on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +WISDOM_API WisResult VKExtendedAllocationCreateGPUUploadTexture(VKExtendedAllocation self, const VKResourceAllocator* allocator, const WisTextureDesc* desc, WisTextureState initial_state, WisMemoryFlags flags, VKTexture* texture); + +/** + * @brief Writes memory directly to the subresource of the texture. + * Subresource is array slice or mip level. + * @param self valid handle to the ExtendedAllocation + * @param host_data The data to write to the texture. + * @param dst_texture The texture to write the data to. + * @param initial_state The initial state of the texture. + * @param region The region to write the data to. + * */ +WISDOM_API WisResult VKExtendedAllocationWriteMemoryToSubresourceDirect(VKExtendedAllocation self, const void* host_data, VKTexture dst_texture, WisTextureState initial_state, WisTextureRegion region); + +/** + * @brief Check if direct GPU upload is supported for the given format. + * @param self valid handle to the ExtendedAllocation + * @param format The format to check. + * @return true if direct GPU upload is supported. + * */ +WISDOM_API bool VKExtendedAllocationSupportedDirectGPUUpload(VKExtendedAllocation self, WisDataFormat format); + +#endif + +#ifdef WISDOM_DX12 +typedef DX12FactoryExtension DX12ExtendedAllocation; +// DX12ExtendedAllocation methods -- +/** + * @brief Creates a texture that is optimized for GPU upload. + * Subsequently this texture may be directly mapped and does not require copying through copy queue. + * The memory behaves as GPU local memory. Requires ReBAR enabled in BIOS. + * @param self valid handle to the ExtendedAllocation + * @param allocator The allocator to create the texture with. + * Allocator must be created by the same device, that initialized this extension. + * @param desc The description of the texture to create. + * @param initial_state The initial state of the texture. Default is Common. + * @param flags The flags of the memory to create the texture with. Default is None. + * @param texture DX12Texture on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +WISDOM_API WisResult DX12ExtendedAllocationCreateGPUUploadTexture(DX12ExtendedAllocation self, const DX12ResourceAllocator* allocator, const WisTextureDesc* desc, WisTextureState initial_state, WisMemoryFlags flags, DX12Texture* texture); + +/** + * @brief Writes memory directly to the subresource of the texture. + * Subresource is array slice or mip level. + * @param self valid handle to the ExtendedAllocation + * @param host_data The data to write to the texture. + * @param dst_texture The texture to write the data to. + * @param initial_state The initial state of the texture. + * @param region The region to write the data to. + * */ +WISDOM_API WisResult DX12ExtendedAllocationWriteMemoryToSubresourceDirect(DX12ExtendedAllocation self, const void* host_data, DX12Texture dst_texture, WisTextureState initial_state, WisTextureRegion region); + +/** + * @brief Check if direct GPU upload is supported for the given format. + * @param self valid handle to the ExtendedAllocation + * @param format The format to check. + * @return true if direct GPU upload is supported. + * */ +WISDOM_API bool DX12ExtendedAllocationSupportedDirectGPUUpload(DX12ExtendedAllocation self, WisDataFormat format); + +#endif + +#if defined(WISDOM_DX12) && !FORCEVK_SWITCH +typedef DX12ExtendedAllocation WisExtendedAllocation; +// WisExtendedAllocation methods -- +/** + * @brief Creates a texture that is optimized for GPU upload. + * Subsequently this texture may be directly mapped and does not require copying through copy queue. + * The memory behaves as GPU local memory. Requires ReBAR enabled in BIOS. + * @param self valid handle to the ExtendedAllocation + * @param allocator The allocator to create the texture with. + * Allocator must be created by the same device, that initialized this extension. + * @param desc The description of the texture to create. + * @param initial_state The initial state of the texture. Default is Common. + * @param flags The flags of the memory to create the texture with. Default is None. + * @param texture WisTexture on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +inline WisResult WisExtendedAllocationCreateGPUUploadTexture(WisExtendedAllocation self, const WisResourceAllocator* allocator, const WisTextureDesc* desc, WisTextureState initial_state, WisMemoryFlags flags, WisTexture* texture) +{ + return DX12ExtendedAllocationCreateGPUUploadTexture(self, allocator, desc, initial_state, flags, texture); +} + +/** + * @brief Writes memory directly to the subresource of the texture. + * Subresource is array slice or mip level. + * @param self valid handle to the ExtendedAllocation + * @param host_data The data to write to the texture. + * @param dst_texture The texture to write the data to. + * @param initial_state The initial state of the texture. + * @param region The region to write the data to. + * */ +inline WisResult WisExtendedAllocationWriteMemoryToSubresourceDirect(WisExtendedAllocation self, const void* host_data, WisTexture dst_texture, WisTextureState initial_state, WisTextureRegion region) +{ + return DX12ExtendedAllocationWriteMemoryToSubresourceDirect(self, host_data, dst_texture, initial_state, region); +} + +/** + * @brief Check if direct GPU upload is supported for the given format. + * @param self valid handle to the ExtendedAllocation + * @param format The format to check. + * @return true if direct GPU upload is supported. + * */ +inline bool WisExtendedAllocationSupportedDirectGPUUpload(WisExtendedAllocation self, WisDataFormat format) +{ + return DX12ExtendedAllocationSupportedDirectGPUUpload(self, format); +} + +#elif defined(WISDOM_VULKAN) + +typedef VKExtendedAllocation WisExtendedAllocation; +// WisExtendedAllocation methods -- +/** + * @brief Creates a texture that is optimized for GPU upload. + * Subsequently this texture may be directly mapped and does not require copying through copy queue. + * The memory behaves as GPU local memory. Requires ReBAR enabled in BIOS. + * @param self valid handle to the ExtendedAllocation + * @param allocator The allocator to create the texture with. + * Allocator must be created by the same device, that initialized this extension. + * @param desc The description of the texture to create. + * @param initial_state The initial state of the texture. Default is Common. + * @param flags The flags of the memory to create the texture with. Default is None. + * @param texture WisTexture on success (StatusOk). + * @return Result with StatusOk on success. + * Error in WisResult::error otherwise. + * */ +inline WisResult WisExtendedAllocationCreateGPUUploadTexture(WisExtendedAllocation self, const WisResourceAllocator* allocator, const WisTextureDesc* desc, WisTextureState initial_state, WisMemoryFlags flags, WisTexture* texture) +{ + return VKExtendedAllocationCreateGPUUploadTexture(self, allocator, desc, initial_state, flags, texture); +} + +/** + * @brief Writes memory directly to the subresource of the texture. + * Subresource is array slice or mip level. + * @param self valid handle to the ExtendedAllocation + * @param host_data The data to write to the texture. + * @param dst_texture The texture to write the data to. + * @param initial_state The initial state of the texture. + * @param region The region to write the data to. + * */ +inline WisResult WisExtendedAllocationWriteMemoryToSubresourceDirect(WisExtendedAllocation self, const void* host_data, WisTexture dst_texture, WisTextureState initial_state, WisTextureRegion region) +{ + return VKExtendedAllocationWriteMemoryToSubresourceDirect(self, host_data, dst_texture, initial_state, region); +} + +/** + * @brief Check if direct GPU upload is supported for the given format. + * @param self valid handle to the ExtendedAllocation + * @param format The format to check. + * @return true if direct GPU upload is supported. + * */ +inline bool WisExtendedAllocationSupportedDirectGPUUpload(WisExtendedAllocation self, WisDataFormat format) +{ + return VKExtendedAllocationSupportedDirectGPUUpload(self, format); +} + +#endif + +//------------------------------------------------------------------------- + #ifdef __cplusplus } #endif diff --git a/bindings/wisdom_ext.inl b/bindings/wisdom_ext.inl index 1b0738d7..f4ce92ab 100644 --- a/bindings/wisdom_ext.inl +++ b/bindings/wisdom_ext.inl @@ -1,7 +1,8 @@ #include "wisdom.h" -#include "wisdom/wisdom_debug.h" -#include "wisdom/wisdom_descriptor_buffer.h" +#include "wisdom/wisdom_debug.hpp" +#include "wisdom/wisdom_descriptor_buffer.hpp" +#include "wisdom/wisdom_extended_allocation.hpp" #if defined(WISDOM_DX12) #include @@ -37,6 +38,10 @@ template<> struct DX12DeviceExtensionMap { using Type = wis::DX12DescriptorBufferExtension; }; +template<> +struct DX12DeviceExtensionMap { + using Type = wis::DX12ExtendedAllocation; +}; //------------------------------------------------------------------------- template typename Executor, typename... Args> @@ -45,6 +50,8 @@ constexpr static inline decltype(auto) DX12DeviceExtensionBridge(wis::DeviceExtI switch (id) { case wis::DeviceExtID::DescriptorBufferExtension: return Executor::Type>{}(std::forward(args)...); + case wis::DeviceExtID::ExtendedAllocation: + return Executor::Type>{}(std::forward(args)...); default: return Executor{}(std::forward(args)...); } @@ -55,12 +62,14 @@ extern "C" WisResult DX12DebugExtensionCreateDebugMessenger(DX12DebugExtension s auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateDebugMessenger(reinterpret_cast(callback), user_data); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *messenger = reinterpret_cast(new (std::nothrow) wis::DX12DebugMessenger(std::move(value))); - if (!*messenger) + if (!*messenger) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12DebugMessenger." }; + } return reinterpret_cast(res); } // DX12DescriptorBufferExtension methods -- @@ -69,12 +78,14 @@ extern "C" WisResult DX12DescriptorBufferExtensionCreateRootSignature(DX12Descri auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateRootSignature(reinterpret_cast(root_constants), constants_count, reinterpret_cast(root_descriptors), descriptors_count, reinterpret_cast(tables), tables_count); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *signature = reinterpret_cast(new (std::nothrow) wis::DX12RootSignature(std::move(value))); - if (!*signature) + if (!*signature) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12RootSignature." }; + } return reinterpret_cast(res); } extern "C" WisResult DX12DescriptorBufferExtensionCreateDescriptorBuffer(DX12DescriptorBufferExtension self, WisDescriptorHeapType type, WisDescriptorMemory memory, uint64_t memory_bytes, DX12DescriptorBuffer* buffer) @@ -82,12 +93,14 @@ extern "C" WisResult DX12DescriptorBufferExtensionCreateDescriptorBuffer(DX12Des auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateDescriptorBuffer(static_cast(type), static_cast(memory), memory_bytes); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *buffer = reinterpret_cast(new (std::nothrow) wis::DX12DescriptorBuffer(std::move(value))); - if (!*buffer) + if (!*buffer) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12DescriptorBuffer." }; + } return reinterpret_cast(res); } extern "C" uint64_t DX12DescriptorBufferExtensionGetDescriptorTableAlignment(DX12DescriptorBufferExtension self, WisDescriptorHeapType type) @@ -114,6 +127,36 @@ extern "C" void DX12DescriptorBufferExtensionSetDescriptorTableOffset(DX12Descri auto* xself = reinterpret_cast(self); xself->SetDescriptorTableOffset(*reinterpret_cast(list), *reinterpret_cast(root_signature), table_index, *reinterpret_cast(buffer), table_aligned_byte_offset); } +// DX12ExtendedAllocation methods -- +extern "C" WisResult DX12ExtendedAllocationCreateGPUUploadTexture(DX12ExtendedAllocation self, const DX12ResourceAllocator* allocator, const WisTextureDesc* desc, WisTextureState initial_state, WisMemoryFlags flags, DX12Texture* texture) +{ + auto* xself = reinterpret_cast(self); + auto&& [res, value] = xself->CreateGPUUploadTexture(*reinterpret_cast(allocator), *reinterpret_cast(desc), static_cast(initial_state), static_cast(flags)); + + if (res.status != wis::Status::Ok) { + return reinterpret_cast(res); + } + + *texture = reinterpret_cast(new (std::nothrow) wis::DX12Texture(std::move(value))); + if (!*texture) { + return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::DX12Texture." }; + } + return reinterpret_cast(res); +} +extern "C" WisResult DX12ExtendedAllocationWriteMemoryToSubresourceDirect(DX12ExtendedAllocation self, const void* host_data, DX12Texture dst_texture, WisTextureState initial_state, WisTextureRegion region) +{ + auto* xself = reinterpret_cast(self); + auto res = xself->WriteMemoryToSubresourceDirect(host_data, *reinterpret_cast(dst_texture), static_cast(initial_state), reinterpret_cast(region)); + ; + return reinterpret_cast(res); +} +extern "C" bool DX12ExtendedAllocationSupportedDirectGPUUpload(DX12ExtendedAllocation self, WisDataFormat format) +{ + auto* xself = reinterpret_cast(self); + auto res = xself->SupportedDirectGPUUpload(static_cast(format)); + ; + return res; +} #endif #if defined(WISDOM_VULKAN) @@ -150,6 +193,10 @@ template<> struct VKDeviceExtensionMap { using Type = wis::VKDescriptorBufferExtension; }; +template<> +struct VKDeviceExtensionMap { + using Type = wis::VKExtendedAllocation; +}; //------------------------------------------------------------------------- template typename Executor, typename... Args> @@ -158,6 +205,8 @@ constexpr static inline decltype(auto) VKDeviceExtensionBridge(wis::DeviceExtID switch (id) { case wis::DeviceExtID::DescriptorBufferExtension: return Executor::Type>{}(std::forward(args)...); + case wis::DeviceExtID::ExtendedAllocation: + return Executor::Type>{}(std::forward(args)...); default: return Executor{}(std::forward(args)...); } @@ -168,12 +217,14 @@ extern "C" WisResult VKDebugExtensionCreateDebugMessenger(VKDebugExtension self, auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateDebugMessenger(reinterpret_cast(callback), user_data); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *messenger = reinterpret_cast(new (std::nothrow) wis::VKDebugMessenger(std::move(value))); - if (!*messenger) + if (!*messenger) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKDebugMessenger." }; + } return reinterpret_cast(res); } // VKDescriptorBufferExtension methods -- @@ -182,12 +233,14 @@ extern "C" WisResult VKDescriptorBufferExtensionCreateRootSignature(VKDescriptor auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateRootSignature(reinterpret_cast(root_constants), constants_count, reinterpret_cast(root_descriptors), descriptors_count, reinterpret_cast(tables), tables_count); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *signature = reinterpret_cast(new (std::nothrow) wis::VKRootSignature(std::move(value))); - if (!*signature) + if (!*signature) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKRootSignature." }; + } return reinterpret_cast(res); } extern "C" WisResult VKDescriptorBufferExtensionCreateDescriptorBuffer(VKDescriptorBufferExtension self, WisDescriptorHeapType type, WisDescriptorMemory memory, uint64_t memory_bytes, VKDescriptorBuffer* buffer) @@ -195,12 +248,14 @@ extern "C" WisResult VKDescriptorBufferExtensionCreateDescriptorBuffer(VKDescrip auto* xself = reinterpret_cast(self); auto&& [res, value] = xself->CreateDescriptorBuffer(static_cast(type), static_cast(memory), memory_bytes); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return reinterpret_cast(res); + } *buffer = reinterpret_cast(new (std::nothrow) wis::VKDescriptorBuffer(std::move(value))); - if (!*buffer) + if (!*buffer) { return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKDescriptorBuffer." }; + } return reinterpret_cast(res); } extern "C" uint64_t VKDescriptorBufferExtensionGetDescriptorTableAlignment(VKDescriptorBufferExtension self, WisDescriptorHeapType type) @@ -227,4 +282,34 @@ extern "C" void VKDescriptorBufferExtensionSetDescriptorTableOffset(VKDescriptor auto* xself = reinterpret_cast(self); xself->SetDescriptorTableOffset(*reinterpret_cast(list), *reinterpret_cast(root_signature), table_index, *reinterpret_cast(buffer), table_aligned_byte_offset); } +// VKExtendedAllocation methods -- +extern "C" WisResult VKExtendedAllocationCreateGPUUploadTexture(VKExtendedAllocation self, const VKResourceAllocator* allocator, const WisTextureDesc* desc, WisTextureState initial_state, WisMemoryFlags flags, VKTexture* texture) +{ + auto* xself = reinterpret_cast(self); + auto&& [res, value] = xself->CreateGPUUploadTexture(*reinterpret_cast(allocator), *reinterpret_cast(desc), static_cast(initial_state), static_cast(flags)); + + if (res.status != wis::Status::Ok) { + return reinterpret_cast(res); + } + + *texture = reinterpret_cast(new (std::nothrow) wis::VKTexture(std::move(value))); + if (!*texture) { + return WisResult{ StatusOutOfMemory, "Failed to allocate memory for wis::VKTexture." }; + } + return reinterpret_cast(res); +} +extern "C" WisResult VKExtendedAllocationWriteMemoryToSubresourceDirect(VKExtendedAllocation self, const void* host_data, VKTexture dst_texture, WisTextureState initial_state, WisTextureRegion region) +{ + auto* xself = reinterpret_cast(self); + auto res = xself->WriteMemoryToSubresourceDirect(host_data, *reinterpret_cast(dst_texture), static_cast(initial_state), reinterpret_cast(region)); + ; + return reinterpret_cast(res); +} +extern "C" bool VKExtendedAllocationSupportedDirectGPUUpload(VKExtendedAllocation self, WisDataFormat format) +{ + auto* xself = reinterpret_cast(self); + auto res = xself->SupportedDirectGPUUpload(static_cast(format)); + ; + return res; +} #endif diff --git a/examples/basic/descriptor_storage/entry_main.cpp b/examples/basic/descriptor_storage/entry_main.cpp index 40413e2b..106b7a8c 100644 --- a/examples/basic/descriptor_storage/entry_main.cpp +++ b/examples/basic/descriptor_storage/entry_main.cpp @@ -35,9 +35,11 @@ class App App() : window("Descriptor Storage", 800, 600) { + wis::Result result = wis::success; + setup.InitDefault(window.GetPlatformExtension()); auto [w, h] = window.PixelSize(); - auto swapx = window.CreateSwapchain(setup); + auto swapx = window.CreateSwapchain(result, setup); std::construct_at(&swap, setup.device, std::move(swapx), w, h); cmd_list = setup.CreateLists(); @@ -46,7 +48,7 @@ class App .cbuffer_count = ex::flight_frames * 2, // one cbuffer per frame .memory = wis::DescriptorMemory::ShaderVisible, // visible to shaders }; - desc_storage = ex::Unwrap(setup.device.CreateDescriptorStorage(desc)); + desc_storage = setup.device.CreateDescriptorStorage(result, desc); } public: @@ -54,8 +56,9 @@ class App { CreateResources(); while (true) { - if (!ProcessEvents()) + if (!ProcessEvents()) { break; + } Frame(); } @@ -97,8 +100,9 @@ class App offsetx += 0.01f; if (offsetx > 1.0f) { offsety += 0.5f; - if (offsety > 1.0f) + if (offsety > 1.0f) { offsety = -1.0f; + } offsetx = -1.0f; } @@ -210,7 +214,7 @@ class App .attachments_count = 1, }, }; - pipeline = ex::Unwrap(setup.device.CreateGraphicsPipeline(&desc)); + pipeline = ex::Unwrap(setup.device.CreateGraphicsPipeline(desc)); } // Create vertex buffer diff --git a/examples/basic/lut/entry_main.cpp b/examples/basic/lut/entry_main.cpp index 207688fc..bf317d7c 100644 --- a/examples/basic/lut/entry_main.cpp +++ b/examples/basic/lut/entry_main.cpp @@ -69,20 +69,21 @@ class App App() : window("LUT", 800, 600) { + wis::Result result = wis::success; wis::DeviceExtension* exts[] = { &desc_ext }; setup.InitDefault(window.GetPlatformExtension(), exts); auto [w, h] = window.PixelSize(); - auto swapx = window.CreateSwapchain(setup); + auto swapx = window.CreateSwapchain(result, setup); std::construct_at(&swap, setup.device, std::move(swapx), w, h); cmd_list = setup.CreateLists(); // Only a single descriptor table with 1 descriptor uint32_t desc_increment = desc_ext.GetDescriptorSize(wis::DescriptorHeapType::Descriptor); - desc_buffer = ex::Unwrap(desc_ext.CreateDescriptorBuffer(wis::DescriptorHeapType::Descriptor, wis::DescriptorMemory::ShaderVisible, 2 * desc_increment)); + desc_buffer = desc_ext.CreateDescriptorBuffer(result, wis::DescriptorHeapType::Descriptor, wis::DescriptorMemory::ShaderVisible, 2 * desc_increment); // No need for multiple samplers uint32_t samp_increment = desc_ext.GetDescriptorSize(wis::DescriptorHeapType::Sampler); - sampler_buffer = ex::Unwrap(desc_ext.CreateDescriptorBuffer(wis::DescriptorHeapType::Sampler, wis::DescriptorMemory::ShaderVisible, 2 * samp_increment)); + sampler_buffer = desc_ext.CreateDescriptorBuffer(result, wis::DescriptorHeapType::Sampler, wis::DescriptorMemory::ShaderVisible, 2 * samp_increment); } public: @@ -90,8 +91,9 @@ class App { CreateResources(); while (true) { - if (!ProcessEvents()) + if (!ProcessEvents()) { break; + } Frame(); } @@ -249,7 +251,7 @@ class App }, .flags = wis::PipelineFlags::DescriptorBuffer, // use descriptor buffer for root signature }; - pipeline = ex::Unwrap(setup.device.CreateGraphicsPipeline(&desc)); + pipeline = ex::Unwrap(setup.device.CreateGraphicsPipeline(desc)); } // Load LUT (using uploaded buffer) @@ -331,7 +333,7 @@ class App .mip_lod_bias = 0.0f, .comparison_op = wis::Compare::None, }; - sampler_lut = ex::Unwrap(device.CreateSampler(&sample_desc)); + sampler_lut = ex::Unwrap(device.CreateSampler(sample_desc)); // Write LUT sampler to the descriptor buffer sampler_buffer.WriteSampler(0, 0, sampler_lut); @@ -410,7 +412,7 @@ class App .mip_lod_bias = 0.0f, .comparison_op = wis::Compare::None, }; - sampler = ex::Unwrap(device.CreateSampler(&sample_desc)); + sampler = ex::Unwrap(device.CreateSampler(sample_desc)); // Write image sampler to the descriptor buffer sampler_buffer.WriteSampler(0, 1, sampler); diff --git a/examples/basic/multiview/entry_main.cpp b/examples/basic/multiview/entry_main.cpp index 2714e2ce..c9bb2b0d 100644 --- a/examples/basic/multiview/entry_main.cpp +++ b/examples/basic/multiview/entry_main.cpp @@ -49,9 +49,10 @@ class App App() : window("Multiview", 800, 600) { + wis::Result result = wis::success; setup.InitDefault(window.GetPlatformExtension()); auto [w, h] = window.PixelSize(); - auto swapx = window.CreateSwapchain(setup); + auto swapx = window.CreateSwapchain(result, setup); std::construct_at(&swap, setup.device, std::move(swapx), w, h); cmd_list = setup.CreateLists(); cmd_list2 = setup.CreateLists(); @@ -67,8 +68,9 @@ class App CreateFirstPassResources(); CreateSecondPassResources(); while (true) { - if (!ProcessEvents()) + if (!ProcessEvents()) { break; + } Frame(); } @@ -314,7 +316,7 @@ class App }, .view_mask = 0b11, // 2 array layers }; - pipeline = ex::Unwrap(setup.device.CreateGraphicsPipeline(&desc)); + pipeline = ex::Unwrap(setup.device.CreateGraphicsPipeline(desc)); } // Create vertex buffer @@ -354,7 +356,7 @@ class App }, // view mask is 0b00, because we will render to the back buffer }; - fullscreen_pipeline = ex::Unwrap(setup.device.CreateGraphicsPipeline(&desc)); + fullscreen_pipeline = ex::Unwrap(setup.device.CreateGraphicsPipeline(desc)); } // Create Sampler @@ -373,7 +375,7 @@ class App .mip_lod_bias = 0.0f, .comparison_op = wis::Compare::None, }; - sampler = ex::Unwrap(setup.device.CreateSampler(&sample_desc)); + sampler = ex::Unwrap(setup.device.CreateSampler(sample_desc)); desc_storage.WriteSampler(0, sampler); } diff --git a/examples/common/window.cpp b/examples/common/window.cpp index 3c92096d..04d1fa3b 100644 --- a/examples/common/window.cpp +++ b/examples/common/window.cpp @@ -1,5 +1,5 @@ #include "window.h" -#include +#include ex::WindowEvent ex::Window::PollEvents() { @@ -42,7 +42,7 @@ ex::WindowEvent ex::Window::PollEvents() return WindowEvent::NoEvent; } -wis::SwapChain ex::Window::CreateSwapchain(ex::ExampleSetup& setup, wis::DataFormat fmt, bool stereo) +wis::SwapChain ex::Window::CreateSwapchain(wis::Result& result, ex::ExampleSetup& setup, wis::DataFormat fmt, bool stereo) { using enum PlatformExtension::Selector; if (_platform.current == None) { @@ -64,8 +64,8 @@ wis::SwapChain ex::Window::CreateSwapchain(ex::ExampleSetup& setup, wis::DataFor case Windows: { HWND hwnd = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); if (hwnd) { - return Unwrap(static_cast(_platform.get()) - ->CreateSwapchain(setup.device, setup.queue, &desc, hwnd)); + return static_cast(_platform.get()) + ->CreateSwapchain(result, setup.device, setup.queue, &desc, hwnd); } } break; #elif defined(SDL_PLATFORM_LINUX) @@ -73,16 +73,16 @@ wis::SwapChain ex::Window::CreateSwapchain(ex::ExampleSetup& setup, wis::DataFor Display* xdisplay = (Display*)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); ::Window xwindow = (::Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); if (xdisplay && xwindow) { - return Unwrap(static_cast(_platform.get()) - ->CreateSwapchain(setup.device, setup.queue, &desc, xdisplay, xwindow)); + return static_cast(_platform.get()) + ->CreateSwapchain(result, setup.device, setup.queue, &desc, xdisplay, xwindow); } } break; case Wayland: { struct wl_display* display = (struct wl_display*)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, NULL); struct wl_surface* surface = (struct wl_surface*)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, NULL); if (display && surface) { - return Unwrap(static_cast(_platform.get()) - ->CreateSwapchain(setup.device, setup.queue, &desc, display, surface)); + return static_cast(_platform.get()) + ->CreateSwapchain(result, setup.device, setup.queue, &desc, display, surface); } } break; #endif @@ -106,12 +106,12 @@ ex::PlatformExtension::PlatformExtension() platform = std::make_unique(); current = Selector::Windows; #elif defined(SDL_PLATFORM_LINUX) - // if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { - platform = std::make_unique(); - current = Selector::X11; - //} else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) { - // platform = std::make_unique(); - // current = Selector::Wayland; - //} + if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { + platform = std::make_unique(); + current = Selector::X11; + } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) { + platform = std::make_unique(); + current = Selector::Wayland; + } #endif } diff --git a/examples/common/window.h b/examples/common/window.h index f86bd13e..6d708879 100644 --- a/examples/common/window.h +++ b/examples/common/window.h @@ -64,7 +64,7 @@ class Window { return _platform.get(); } - wis::SwapChain CreateSwapchain(ex::ExampleSetup& setup, wis::DataFormat fmt = ex::swapchain_format, bool stereo = false); + wis::SwapChain CreateSwapchain(wis::Result& result, ex::ExampleSetup& setup, wis::DataFormat fmt = ex::swapchain_format, bool stereo = false); void PostQuit(); ex::WindowEvent PollEvents(); diff --git a/examples/common/wis_helper.cpp b/examples/common/wis_helper.cpp index ef952dc2..62576aac 100644 --- a/examples/common/wis_helper.cpp +++ b/examples/common/wis_helper.cpp @@ -15,26 +15,28 @@ wis::Factory ex::ExampleSetup::InitDefaultFactory(wis::FactoryExtension* platfor using namespace wis; wis::DebugExtension debug_ext; // no need to store it, it will be destroyed when it goes out of scope + wis::Result res; wis::FactoryExtension* xfactory_exts[] = { &debug_ext, platform_ext }; - wis::Factory factory = Unwrap(wis::CreateFactory(true, xfactory_exts, std::size(xfactory_exts))); - info = Unwrap(debug_ext.CreateDebugMessenger(&DebugCallback, &std::cout)); - return std::move(factory); + wis::Factory factory = wis::CreateFactory(res, true, xfactory_exts, std::size(xfactory_exts)); + info = debug_ext.CreateDebugMessenger(res, &DebugCallback, &std::cout); + return factory; } void ex::ExampleSetup::InitDefaultDevice(const wis::Factory& factory, std::span device_exts) { + wis::Result result = wis::success; for (size_t i = 0;; i++) { - auto [res, adapter] = factory.GetAdapter(i); - if (res.status != wis::Status::Ok) + auto adapter = factory.GetAdapter(result, i); + if (result.status != wis::Status::Ok) { break; + } wis::AdapterDesc desc; - res = adapter.GetDesc(&desc); + result = adapter.GetDesc(&desc); std::cout << "Adapter: " << desc.description.data() << "\n"; - auto [res2, hdevice] = wis::CreateDevice(std::move(adapter), device_exts.data(), device_exts.size()); - if (res2.status == wis::Status::Ok) { - device = std::move(hdevice); + device = wis::CreateDevice(result, std::move(adapter), device_exts.data(), device_exts.size()); + if (result.status == wis::Status::Ok) { return; } } @@ -63,13 +65,15 @@ void ex::ExampleSetup::WaitForGPU() std::string ex::LoadShader(std::filesystem::path p) { - if constexpr (wis::shader_intermediate == wis::ShaderIntermediate::DXIL) + if constexpr (wis::shader_intermediate == wis::ShaderIntermediate::DXIL) { p += u".cso"; - else + } else { p += u".spv"; + } - if (!std::filesystem::exists(p)) + if (!std::filesystem::exists(p)) { throw Exception(wis::format("Shader file not found: {}", p.string())); + } std::ifstream t{ p, std::ios::binary }; t.seekg(0, std::ios::end); diff --git a/examples/common/wis_helper.h b/examples/common/wis_helper.h index f78dae82..3a7ffd2c 100644 --- a/examples/common/wis_helper.h +++ b/examples/common/wis_helper.h @@ -1,7 +1,7 @@ #pragma once #include -#include -#include +#include +#include #include #include #include @@ -23,8 +23,9 @@ struct Exception : public std::exception { inline void CheckResult(wis::Result res) { - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { throw Exception(res.error); + } } template inline T Unwrap(wis::ResultValue&& res) diff --git a/examples/custom/cross_device/app.cpp b/examples/custom/cross_device/app.cpp index b8d5dd6c..fd3bfaf1 100644 --- a/examples/custom/cross_device/app.cpp +++ b/examples/custom/cross_device/app.cpp @@ -1,7 +1,7 @@ #include "app.h" #include #include -#include +#include #include #include @@ -39,13 +39,15 @@ void App::CreateDevices() wis::FactoryExtension* extensions[] = { &windows_ext, &debug_ext }; auto [result, factory] = wis::CreateFactory(false, extensions, std::size(extensions)); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { throw std::runtime_error("Failed to create factory"); + } // Create debug messenger auto [result2, hinfo] = debug_ext.CreateDebugMessenger(DebugCallback, nullptr); - if (result2.status != wis::Status::Ok) + if (result2.status != wis::Status::Ok) { throw std::runtime_error("Failed to create debug messenger"); + } info = std::move(hinfo); @@ -58,21 +60,25 @@ void App::CreateDevices() if (!transfer.transfer_device) { std::cout << wis::format("Work adapter: {}\n", desc.description.data()); auto result = CreateTransferNode(std::move(adapter)); - if (result) + if (result) { transfer = std::move(result.value()); + } continue; } if (!work.work_device) { std::cout << wis::format("Work adapter: {}\n", desc.description.data()); auto result = CreateWorkNode(std::move(adapter)); - if (result) + if (result) { work = std::move(result.value()); + } } } else { - if (!work.work_device) + if (!work.work_device) { throw std::runtime_error("Failed to create work device"); - if (!transfer.transfer_device) + } + if (!transfer.transfer_device) { throw std::runtime_error("Failed to create transfer device"); + } break; } } @@ -93,8 +99,9 @@ void App::CreateSwapChain(const wis::platform::WindowsExtension& platform) .tearing = false, }; auto [result, swap] = platform.CreateSwapchain(transfer.transfer_device, transfer.queue, &desc, wnd.GetHandle()); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { throw std::runtime_error("Failed to create swapchain"); + } transfer.InitSwapchain(std::move(swap)); work.CreateOutputTexture(desc.size); @@ -111,14 +118,16 @@ int App::Start() uint32_t frame_count = 0; long long elapsed = 0; while (frame_count != 100) { - if (const auto a = wnd.ProcessMessages()) + if (const auto a = wnd.ProcessMessages()) { return (int)a.value(); + } - for (auto e : wnd.GetEvents()) + for (auto e : wnd.GetEvents()) { switch (e) { case Event::Resize: OnResize(wnd.GetWidth(), wnd.GetHeight()); } + } auto start = std::chrono::high_resolution_clock::now(); Frame(); @@ -133,8 +142,9 @@ int App::Start() void App::OnResize(uint32_t width, uint32_t height) { - if (width == this->width && height == this->height) + if (width == this->width && height == this->height) { return; + } transfer.input_buffer.Unmap(); work.CreateOutputTexture({ width, height }); diff --git a/examples/custom/cross_device/app.h b/examples/custom/cross_device/app.h index 0d7ab95e..aa4820ee 100644 --- a/examples/custom/cross_device/app.h +++ b/examples/custom/cross_device/app.h @@ -2,7 +2,7 @@ #include "window.h" #include "work_node.h" #include "transfer_node.h" -#include +#include class App { diff --git a/examples/custom/cross_device/transfer_node.h b/examples/custom/cross_device/transfer_node.h index f3bc0be1..7719733f 100644 --- a/examples/custom/cross_device/transfer_node.h +++ b/examples/custom/cross_device/transfer_node.h @@ -1,7 +1,7 @@ #pragma once #include -#include -#include +#include +#include #include #include #include diff --git a/examples/custom/cross_device/work_node.cpp b/examples/custom/cross_device/work_node.cpp index cfddfc46..467ca7ad 100644 --- a/examples/custom/cross_device/work_node.cpp +++ b/examples/custom/cross_device/work_node.cpp @@ -11,21 +11,24 @@ std::expected LoadShader(std::filesystem::path p) noexcept { - if constexpr (wis::shader_intermediate == wis::ShaderIntermediate::DXIL) + if constexpr (wis::shader_intermediate == wis::ShaderIntermediate::DXIL) { p += u".cso"; - else + } else { p += u".spv"; + } - if (!std::filesystem::exists(p)) + if (!std::filesystem::exists(p)) { return std::expected{ std::unexpect, "File not found" }; + } std::ifstream t{ p, std::ios::binary }; - if (!t.is_open()) + if (!t.is_open()) { return std::expected{ std::unexpect, "Failed to open file" }; + } t.seekg(0, std::ios::end); size_t size = t.tellg(); @@ -72,24 +75,27 @@ CreateWorkNode(wis::Adapter&& adapter) // Create Device { auto [res, device] = wis::CreateDevice(adapter, extensions, std::size(extensions)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.work_device = std::move(device); } // Create Graphics Queue { auto [res, queue] = node.work_device.CreateCommandQueue(wis::QueueType::Graphics); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.queue = std::move(queue); } // Create Resource Allocator { auto [res, allocator] = node.work_device.CreateAllocator(); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.allocator = std::move(allocator); } @@ -98,8 +104,9 @@ CreateWorkNode(wis::Adapter&& adapter) using namespace wis; LutLoader loader; auto lut_data = loader.LoadLut("lut.cube"); - if (lut_data.type == LutType::Undefined) + if (lut_data.type == LutType::Undefined) { return std::unexpected("Invalid LUT file"); + } wis::TextureDesc desc{ .format = wis::DataFormat::RGBA32Float, @@ -108,8 +115,9 @@ CreateWorkNode(wis::Adapter&& adapter) .usage = wis::TextureUsage::ShaderResource | wis::TextureUsage::HostCopy }; auto [res, texture] = node.extended_alloc.CreateGPUUploadTexture(node.allocator, desc, wis::TextureState::CopyDest, wis::MemoryFlags::DedicatedAllocation); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } wis::TextureRegion region{ .offset = { 0, 0, 0 }, @@ -117,8 +125,9 @@ CreateWorkNode(wis::Adapter&& adapter) .format = wis::DataFormat::RGBA32Float }; auto res2 = node.extended_alloc.WriteMemoryToSubresourceDirect(lut_data.data.get(), texture, wis::TextureState::CopyDest, region); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.lut = std::move(texture); } @@ -135,8 +144,9 @@ CreateWorkNode(wis::Adapter&& adapter) .usage = wis::TextureUsage::ShaderResource | wis::TextureUsage::HostCopy }; auto [res, texture] = node.extended_alloc.CreateGPUUploadTexture(node.allocator, desc, wis::TextureState::CopyDest, wis::MemoryFlags::DedicatedAllocation); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } wis::TextureRegion region{ .offset = { 0, 0, 0 }, @@ -144,8 +154,9 @@ CreateWorkNode(wis::Adapter&& adapter) .format = wis::DataFormat::RGBA8Unorm }; auto res2 = node.extended_alloc.WriteMemoryToSubresourceDirect(data.data.data(), texture, wis::TextureState::CopyDest, region); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.texture = std::move(texture); } @@ -159,8 +170,9 @@ CreateWorkNode(wis::Adapter&& adapter) .subresource_range = { 0, 1, 0, 1 } }; auto [res, srv] = node.work_device.CreateShaderResource(node.lut, desc); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.srv_lut = std::move(srv); } @@ -173,8 +185,9 @@ CreateWorkNode(wis::Adapter&& adapter) .subresource_range = { 0, 1, 0, 1 } }; auto [res, srv] = node.work_device.CreateShaderResource(node.texture, desc); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.srv = std::move(srv); } @@ -192,9 +205,10 @@ CreateWorkNode(wis::Adapter&& adapter) .mip_lod_bias = 0.0f, .comparison_op = wis::Compare::None, }; - auto [res, sampler] = node.work_device.CreateSampler(&sample_desc); - if (res.status != wis::Status::Ok) + auto [res, sampler] = node.work_device.CreateSampler(sample_desc); + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.sampler = std::move(sampler); } @@ -203,18 +217,22 @@ CreateWorkNode(wis::Adapter&& adapter) auto sv = LoadShader("lut.vs"); auto sp = LoadShader("lut_tetra.ps"); - if (!sv) + if (!sv) { return std::unexpected(sp.error()); - if (!sp) + } + if (!sp) { return std::unexpected(sp.error()); + } auto [res, vertex_shader] = node.work_device.CreateShader(sv.value().data(), sv.value().size()); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } auto [res2, pixel_shader] = node.work_device.CreateShader(sp.value().data(), sp.value().size()); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.vertex_shader = std::move(vertex_shader); node.pixel_shader = std::move(pixel_shader); @@ -260,8 +278,9 @@ CreateWorkNode(wis::Adapter&& adapter) }; auto [result, root] = node.desc_buffer_ext.CreateRootSignature(nullptr, 0, nullptr, 0, tables, sizeof(tables) / sizeof(tables[0])); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return std::unexpected(result.error); + } node.root = std::move(root); } @@ -276,25 +295,28 @@ CreateWorkNode(wis::Adapter&& adapter) }, .flags = wis::PipelineFlags::DescriptorBuffer, }; - auto [res2, hpipeline] = node.work_device.CreateGraphicsPipeline(&desc); - if (res2.status != wis::Status::Ok) + auto [res2, hpipeline] = node.work_device.CreateGraphicsPipeline(desc); + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.pipeline = std::move(hpipeline); } // Create Fence { auto [res, fence] = node.work_device.CreateFence(0); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.fence = std::move(fence); } // Create Command List { auto [res, cmd_list] = node.work_device.CreateCommandList(wis::QueueType::Graphics); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.cmd_list = std::move(cmd_list); } @@ -302,13 +324,15 @@ CreateWorkNode(wis::Adapter&& adapter) { auto desc_increment = node.desc_buffer_ext.GetDescriptorSize(wis::DescriptorHeapType::Descriptor); auto [res, hdesc] = node.desc_buffer_ext.CreateDescriptorBuffer(wis::DescriptorHeapType::Descriptor, wis::DescriptorMemory::ShaderVisible, 2 * desc_increment); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } auto sampler_increment = node.desc_buffer_ext.GetDescriptorSize(wis::DescriptorHeapType::Sampler); auto [res2, hdesc2] = node.desc_buffer_ext.CreateDescriptorBuffer(wis::DescriptorHeapType::Sampler, wis::DescriptorMemory::ShaderVisible, 1 * sampler_increment); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } // Set Descriptor Buffers hdesc.WriteShaderResource(0, 1, node.srv); @@ -371,8 +395,9 @@ void WorkNode::CreateOutputTexture(wis::Size2D frame) .usage = wis::TextureUsage::RenderTarget | wis::TextureUsage::CopySrc, }; auto [result, tex] = allocator.CreateTexture(desc); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return; + } // Create render target { @@ -380,8 +405,9 @@ void WorkNode::CreateOutputTexture(wis::Size2D frame) .format = wis::DataFormat::RGBA8Unorm, }; auto [res, rt] = work_device.CreateRenderTarget(tex, rt_desc); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return; + } render_target = std::move(rt); } @@ -482,9 +508,6 @@ void WorkNode::Frame() void WorkNode::ImportExternalBuffer(void* mapping, uint64_t size) { - auto [res, buffer] = ext_mem_host.CreateExternalBuffer(allocator, mapping, size); - if (res.status != wis::Status::Ok) - return; - - ext_buffer = std::move(buffer); + wis::Result result = wis::success; + ext_buffer = ext_mem_host.CreateExternalBuffer(result, allocator, mapping, size); } diff --git a/examples/custom/cross_device/work_node.h b/examples/custom/cross_device/work_node.h index 0ec203aa..e5276199 100644 --- a/examples/custom/cross_device/work_node.h +++ b/examples/custom/cross_device/work_node.h @@ -1,7 +1,7 @@ #pragma once #include -#include -#include +#include +#include #include struct ExternalBuffer { @@ -16,8 +16,9 @@ struct ExternalBuffer { } ExternalBuffer& operator=(ExternalBuffer&& other) noexcept { - if (this == &other) + if (this == &other) { return *this; + } Destroy(); device = std::move(other.device); @@ -27,10 +28,12 @@ struct ExternalBuffer { } void Destroy() noexcept { - if (buffer) + if (buffer) { device.table().vkDestroyBuffer(device.get(), buffer, nullptr); - if (memory) + } + if (memory) { device.table().vkFreeMemory(device.get(), memory, nullptr); + } } ~ExternalBuffer() { @@ -60,8 +63,9 @@ struct ExtMemoryHost : public wis::DeviceExtension { std::unordered_map& structure_map, std::unordered_map& property_map) noexcept override { - if (available_extensions.find(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME) == available_extensions.end()) + if (available_extensions.find(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME) == available_extensions.end()) { return false; + } ext_name_set.insert(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); property_map[VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT] = sizeof(VkPhysicalDeviceExternalMemoryHostPropertiesEXT); @@ -87,8 +91,10 @@ struct ExtMemoryHost : public wis::DeviceExtension { return vkGetMemoryHostPointerPropertiesEXT; } - wis::ResultValue CreateExternalBuffer(wis::ResourceAllocator allocator, void* mapping, uint64_t size) + ExternalBuffer CreateExternalBuffer(wis::Result& result, wis::ResourceAllocator allocator, void* mapping, uint64_t size) const noexcept { + ExternalBuffer buffer; + uint32_t mem_idx = 0; VkMemoryHostPointerPropertiesEXT props{ .sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT, @@ -97,8 +103,10 @@ struct ExtMemoryHost : public wis::DeviceExtension { VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, mapping, &props); - if (res != VK_SUCCESS) - return wis::make_result(res); + if (res != VK_SUCCESS) { + result = wis::make_result(res); + return buffer; + } VmaAllocationCreateInfo xalloc_info{ //.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, @@ -135,26 +143,29 @@ struct ExtMemoryHost : public wis::DeviceExtension { .allocationSize = wis::detail::aligned_size(size, size_alignment), .memoryTypeIndex = mem_idx, }; - VkDeviceMemory memory; - res = shared_device.table().vkAllocateMemory(shared_device.get(), &alloc_info, nullptr, &memory); - if (res != VK_SUCCESS) - return wis::make_result(res); - - VkBuffer buffer; - - res = shared_device.table().vkCreateBuffer(shared_device.get(), &buffer_info, nullptr, &buffer); + res = shared_device.table().vkAllocateMemory(shared_device.get(), &alloc_info, nullptr, &buffer.memory); if (res != VK_SUCCESS) { - shared_device.table().vkFreeMemory(shared_device.get(), memory, nullptr); - return wis::make_result(res); + result = wis::make_result(res); + return buffer; + } + res = shared_device.table().vkCreateBuffer(shared_device.get(), &buffer_info, nullptr, &buffer.buffer); + if (res != VK_SUCCESS) { + shared_device.table().vkFreeMemory(shared_device.get(), buffer.memory, nullptr); + buffer.memory = nullptr; + + result = wis::make_result(res); + return buffer; } - res = shared_device.table().vkBindBufferMemory(shared_device.get(), buffer, memory, 0); + res = shared_device.table().vkBindBufferMemory(shared_device.get(), buffer.buffer, buffer.memory, 0); if (res != VK_SUCCESS) { - shared_device.table().vkDestroyBuffer(shared_device.get(), buffer, nullptr); - shared_device.table().vkFreeMemory(shared_device.get(), memory, nullptr); - return wis::make_result(res); + shared_device.table().vkDestroyBuffer(shared_device.get(), buffer.buffer, nullptr); + shared_device.table().vkFreeMemory(shared_device.get(), buffer.memory, nullptr); + buffer.buffer = nullptr; + buffer.memory = nullptr; + result = wis::make_result(res); } - return ExternalBuffer(shared_device, buffer, memory); + return buffer; } }; diff --git a/examples/custom/multimon/app.cpp b/examples/custom/multimon/app.cpp index a6b6ce5f..47e2f724 100644 --- a/examples/custom/multimon/app.cpp +++ b/examples/custom/multimon/app.cpp @@ -1,7 +1,7 @@ #include "app.h" #include #include -#include +#include #include #include @@ -37,13 +37,15 @@ void App::CreateDevices() wis::FactoryExtension* extensions[] = { &windows_ext, &debug_ext }; auto [result, factory] = wis::CreateFactory(false, extensions, std::size(extensions)); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { throw std::runtime_error("Failed to create factory"); + } // Create debug messenger auto [result2, hinfo] = debug_ext.CreateDebugMessenger(DebugCallback, nullptr); - if (result2.status != wis::Status::Ok) + if (result2.status != wis::Status::Ok) { throw std::runtime_error("Failed to create debug messenger"); + } info = std::move(hinfo); @@ -56,21 +58,25 @@ void App::CreateDevices() if (!transfer.transfer_device) { std::cout << wis::format("Work adapter: {}\n", desc.description.data()); auto result = CreateTransferNode(std::move(adapter)); - if (result) + if (result) { transfer = std::move(result.value()); + } continue; } if (!work.work_device) { std::cout << wis::format("Work adapter: {}\n", desc.description.data()); auto result = CreateWorkNode(std::move(adapter)); - if (result) + if (result) { work = std::move(result.value()); + } } } else { - if (!work.work_device) + if (!work.work_device) { throw std::runtime_error("Failed to create work device"); - if (!transfer.transfer_device) + } + if (!transfer.transfer_device) { throw std::runtime_error("Failed to create transfer device"); + } break; } } @@ -90,13 +96,15 @@ void App::CreateSwapChain(const wis::platform::WindowsExtension& platform) }; auto [result, swap] = platform.CreateSwapchain(transfer.transfer_device, transfer.queue, &desc, wnd.GetHandle()); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { throw std::runtime_error("Failed to create swapchain"); + } desc.size = { uint32_t(wnd2.GetWidth()), uint32_t(wnd2.GetHeight()) }; auto [result2, swap2] = platform.CreateSwapchain(transfer.transfer_device, transfer.queue, &desc, wnd2.GetHandle()); - if (result2.status != wis::Status::Ok) + if (result2.status != wis::Status::Ok) { throw std::runtime_error("Failed to create swapchain"); + } transfer.InitSwapchain(std::move(swap2), std::move(swap)); // Create output texture @@ -110,24 +118,28 @@ int App::Start() uint32_t frame_count = 0; long long elapsed = 0; while (frame_count != 1000) { - if (const auto a = wnd.ProcessMessages()) + if (const auto a = wnd.ProcessMessages()) { return (int)a.value(); + } - if (const auto a = wnd2.ProcessMessages()) + if (const auto a = wnd2.ProcessMessages()) { return (int)a.value(); + } - for (auto e : wnd.GetEvents()) + for (auto e : wnd.GetEvents()) { switch (e) { case Event::Resize: OnResize(wnd.GetWidth(), wnd.GetHeight(), 0); break; } - for (auto e : wnd2.GetEvents()) + } + for (auto e : wnd2.GetEvents()) { switch (e) { case Event::Resize: OnResize(wnd2.GetWidth(), wnd2.GetHeight(), 1); break; } + } auto start = std::chrono::high_resolution_clock::now(); Frame(); diff --git a/examples/custom/multimon/app.h b/examples/custom/multimon/app.h index 90ba0f59..eea78efa 100644 --- a/examples/custom/multimon/app.h +++ b/examples/custom/multimon/app.h @@ -2,7 +2,7 @@ #include "window.h" #include "work_node.h" #include "transfer_node.h" -#include +#include class App { diff --git a/examples/custom/multimon/transfer_node.cpp b/examples/custom/multimon/transfer_node.cpp index 32b32023..1dee0ad0 100644 --- a/examples/custom/multimon/transfer_node.cpp +++ b/examples/custom/multimon/transfer_node.cpp @@ -6,21 +6,24 @@ static std::expected LoadShader(std::filesystem::path p) noexcept { - if constexpr (wis::shader_intermediate == wis::ShaderIntermediate::DXIL) + if constexpr (wis::shader_intermediate == wis::ShaderIntermediate::DXIL) { p += u".cso"; - else + } else { p += u".spv"; + } - if (!std::filesystem::exists(p)) + if (!std::filesystem::exists(p)) { return std::expected{ std::unexpect, "File not found" }; + } std::ifstream t{ p, std::ios::binary }; - if (!t.is_open()) + if (!t.is_open()) { return std::expected{ std::unexpect, "Failed to open file" }; + } t.seekg(0, std::ios::end); size_t size = t.tellg(); @@ -44,8 +47,9 @@ CreateTransferNode(wis::Adapter&& adapter) &node.desc_buffer_ext }; auto [result, device] = wis::CreateDevice(adapter, exts, std::size(exts)); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return std::unexpected(result.error); + } node.transfer_device = std::move(device); } @@ -53,8 +57,9 @@ CreateTransferNode(wis::Adapter&& adapter) // Create allocator { auto [result, allocator] = node.transfer_device.CreateAllocator(); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return std::unexpected(result.error); + } node.allocator = std::move(allocator); } @@ -63,8 +68,9 @@ CreateTransferNode(wis::Adapter&& adapter) { // Has to be graphics queue for copy operations, because present auto [result, queue] = node.transfer_device.CreateCommandQueue(wis::QueueType::Graphics); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return std::unexpected(result.error); + } node.queue = std::move(queue); } @@ -72,8 +78,9 @@ CreateTransferNode(wis::Adapter&& adapter) // Create Fence { auto [result, fence] = node.transfer_device.CreateFence(); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return std::unexpected(result.error); + } node.fence = std::move(fence); } @@ -81,10 +88,12 @@ CreateTransferNode(wis::Adapter&& adapter) { auto [result, cmd_list] = node.transfer_device.CreateCommandList(wis::QueueType::Graphics); auto [result2, cmd_list2] = node.transfer_device.CreateCommandList(wis::QueueType::Graphics); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return std::unexpected(result.error); - if (result2.status != wis::Status::Ok) + } + if (result2.status != wis::Status::Ok) { return std::unexpected(result2.error); + } node.cmd_list = std::move(cmd_list); node.copy_cmd_list = std::move(cmd_list2); } @@ -94,18 +103,22 @@ CreateTransferNode(wis::Adapter&& adapter) auto sv = LoadShader("present.vs"); auto sp = LoadShader("present.ps"); - if (!sv) + if (!sv) { return std::unexpected(sp.error()); - if (!sp) + } + if (!sp) { return std::unexpected(sp.error()); + } auto [res, vertex_shader] = node.transfer_device.CreateShader(sv.value().data(), sv.value().size()); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } auto [res2, pixel_shader] = node.transfer_device.CreateShader(sp.value().data(), sp.value().size()); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.vs = std::move(vertex_shader); node.ps = std::move(pixel_shader); @@ -151,8 +164,9 @@ CreateTransferNode(wis::Adapter&& adapter) }, }; auto [result, root] = node.desc_buffer_ext.CreateRootSignature(constants, 1, nullptr, 0, tables, sizeof(tables) / sizeof(tables[0])); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return std::unexpected(result.error); + } node.root_signature = std::move(root); } @@ -167,9 +181,10 @@ CreateTransferNode(wis::Adapter&& adapter) }, .flags = wis::PipelineFlags::DescriptorBuffer, }; - auto [res2, hpipeline] = node.transfer_device.CreateGraphicsPipeline(&desc); - if (res2.status != wis::Status::Ok) + auto [res2, hpipeline] = node.transfer_device.CreateGraphicsPipeline(desc); + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.pipeline_state = std::move(hpipeline); } @@ -187,9 +202,10 @@ CreateTransferNode(wis::Adapter&& adapter) .mip_lod_bias = 0.0f, .comparison_op = wis::Compare::None, }; - auto [r, s] = node.transfer_device.CreateSampler(&desc); - if (r.status != wis::Status::Ok) + auto [r, s] = node.transfer_device.CreateSampler(desc); + if (r.status != wis::Status::Ok) { return std::unexpected(r.error); + } node.sampler = std::move(s); } @@ -199,13 +215,15 @@ CreateTransferNode(wis::Adapter&& adapter) auto unit_size = node.desc_buffer_ext.GetDescriptorSize(wis::DescriptorHeapType::Descriptor); auto [res, hdesc] = node.desc_buffer_ext.CreateDescriptorBuffer(wis::DescriptorHeapType::Descriptor, wis::DescriptorMemory::ShaderVisible, unit_size); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } unit_size = node.desc_buffer_ext.GetDescriptorSize(wis::DescriptorHeapType::Sampler); auto [res2, hdesc2] = node.desc_buffer_ext.CreateDescriptorBuffer(wis::DescriptorHeapType::Sampler, wis::DescriptorMemory::ShaderVisible, unit_size); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } // Set Descriptor Buffers hdesc2.WriteSampler(0, 0, node.sampler); @@ -243,8 +261,9 @@ void TransferNode::Resize(uint32_t width, uint32_t height, uint32_t swapn) { wis::Size2D xframe_size = { width, height }; auto result = swap[swapn].Resize(width, height); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return; + } back_buffers[swapn] = swap[swapn].GetBufferSpan(); frame_size[swapn] = xframe_size; @@ -264,8 +283,8 @@ void TransferNode::VKImportFrame(wis::Size2D frame, void* mapping) { using namespace wis; // create an external buffer - auto [r, b] = ext_mem_host.CreateExternalBuffer(allocator, mapping, frame.width * frame.height * 4); - input_buffer = std::move(b); + wis::Result result = success; + input_buffer = ext_mem_host.CreateExternalBuffer(result, allocator, mapping, frame.width * frame.height * 4); // create debug buffer auto [r1, b1] = allocator.CreateReadbackBuffer(frame.width * frame.height * 4); diff --git a/examples/custom/multimon/transfer_node.h b/examples/custom/multimon/transfer_node.h index 09f594cf..114ad0c7 100644 --- a/examples/custom/multimon/transfer_node.h +++ b/examples/custom/multimon/transfer_node.h @@ -1,8 +1,8 @@ #pragma once #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -20,8 +20,9 @@ struct ExternalBuffer { } ExternalBuffer& operator=(ExternalBuffer&& other) noexcept { - if (this == &other) + if (this == &other) { return *this; + } Destroy(); device = std::move(other.device); @@ -31,10 +32,12 @@ struct ExternalBuffer { } void Destroy() noexcept { - if (buffer) + if (buffer) { device.table().vkDestroyBuffer(device.get(), buffer, nullptr); - if (memory) + } + if (memory) { device.table().vkFreeMemory(device.get(), memory, nullptr); + } } ~ExternalBuffer() { @@ -64,8 +67,9 @@ struct ExtMemoryHost : public wis::DeviceExtension { std::unordered_map& structure_map, std::unordered_map& property_map) noexcept override { - if (available_extensions.find(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME) == available_extensions.end()) + if (available_extensions.find(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME) == available_extensions.end()) { return false; + } ext_name_set.insert(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); property_map[VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT] = sizeof(VkPhysicalDeviceExternalMemoryHostPropertiesEXT); @@ -91,8 +95,10 @@ struct ExtMemoryHost : public wis::DeviceExtension { return vkGetMemoryHostPointerPropertiesEXT; } - wis::ResultValue CreateExternalBuffer(wis::ResourceAllocator allocator, void* mapping, uint64_t size) + ExternalBuffer CreateExternalBuffer(wis::Result& result, wis::ResourceAllocator allocator, void* mapping, uint64_t size) const noexcept { + ExternalBuffer buffer; + uint32_t mem_idx = 0; VkMemoryHostPointerPropertiesEXT props{ .sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT, @@ -101,12 +107,14 @@ struct ExtMemoryHost : public wis::DeviceExtension { VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, mapping, &props); - if (res != VK_SUCCESS) - return wis::make_result(res); + if (res != VK_SUCCESS) { + result = wis::make_result(res); + return buffer; + } VmaAllocationCreateInfo xalloc_info{ //.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT, - .usage = VMA_MEMORY_USAGE_CPU_TO_GPU, + .usage = VMA_MEMORY_USAGE_GPU_TO_CPU, .requiredFlags = 0, .preferredFlags = 0, .memoryTypeBits = props.memoryTypeBits, @@ -124,7 +132,7 @@ struct ExtMemoryHost : public wis::DeviceExtension { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = &ext_info, .size = size, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, }; @@ -139,26 +147,29 @@ struct ExtMemoryHost : public wis::DeviceExtension { .allocationSize = wis::detail::aligned_size(size, size_alignment), .memoryTypeIndex = mem_idx, }; - VkDeviceMemory memory; - res = shared_device.table().vkAllocateMemory(shared_device.get(), &alloc_info, nullptr, &memory); - if (res != VK_SUCCESS) - return wis::make_result(res); - - VkBuffer buffer; - - res = shared_device.table().vkCreateBuffer(shared_device.get(), &buffer_info, nullptr, &buffer); + res = shared_device.table().vkAllocateMemory(shared_device.get(), &alloc_info, nullptr, &buffer.memory); if (res != VK_SUCCESS) { - shared_device.table().vkFreeMemory(shared_device.get(), memory, nullptr); - return wis::make_result(res); + result = wis::make_result(res); + return buffer; + } + res = shared_device.table().vkCreateBuffer(shared_device.get(), &buffer_info, nullptr, &buffer.buffer); + if (res != VK_SUCCESS) { + shared_device.table().vkFreeMemory(shared_device.get(), buffer.memory, nullptr); + buffer.memory = nullptr; + + result = wis::make_result(res); + return buffer; } - res = shared_device.table().vkBindBufferMemory(shared_device.get(), buffer, memory, 0); + res = shared_device.table().vkBindBufferMemory(shared_device.get(), buffer.buffer, buffer.memory, 0); if (res != VK_SUCCESS) { - shared_device.table().vkDestroyBuffer(shared_device.get(), buffer, nullptr); - shared_device.table().vkFreeMemory(shared_device.get(), memory, nullptr); - return wis::make_result(res); + shared_device.table().vkDestroyBuffer(shared_device.get(), buffer.buffer, nullptr); + shared_device.table().vkFreeMemory(shared_device.get(), buffer.memory, nullptr); + buffer.buffer = nullptr; + buffer.memory = nullptr; + result = wis::make_result(res); } - return ExternalBuffer(shared_device, buffer, memory); + return buffer; } }; diff --git a/examples/custom/multimon/work_node.cpp b/examples/custom/multimon/work_node.cpp index a8729882..bcbf016e 100644 --- a/examples/custom/multimon/work_node.cpp +++ b/examples/custom/multimon/work_node.cpp @@ -10,21 +10,24 @@ static std::expected LoadShader(std::filesystem::path p) noexcept { - if constexpr (wis::shader_intermediate == wis::ShaderIntermediate::DXIL) + if constexpr (wis::shader_intermediate == wis::ShaderIntermediate::DXIL) { p += u".cso"; - else + } else { p += u".spv"; + } - if (!std::filesystem::exists(p)) + if (!std::filesystem::exists(p)) { return std::expected{ std::unexpect, "File not found" }; + } std::ifstream t{ p, std::ios::binary }; - if (!t.is_open()) + if (!t.is_open()) { return std::expected{ std::unexpect, "Failed to open file" }; + } t.seekg(0, std::ios::end); size_t size = t.tellg(); @@ -70,24 +73,27 @@ CreateWorkNode(wis::Adapter&& adapter) // Create Device { auto [res, device] = wis::CreateDevice(adapter, extensions, std::size(extensions)); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.work_device = std::move(device); } // Create Graphics Queue { auto [res, queue] = node.work_device.CreateCommandQueue(wis::QueueType::Graphics); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.queue = std::move(queue); } // Create Resource Allocator { auto [res, allocator] = node.work_device.CreateAllocator(); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.allocator = std::move(allocator); } @@ -96,8 +102,9 @@ CreateWorkNode(wis::Adapter&& adapter) using namespace wis; LutLoader loader; auto lut_data = loader.LoadLut("lut.cube"); - if (lut_data.type == LutType::Undefined) + if (lut_data.type == LutType::Undefined) { return std::unexpected("Invalid LUT file"); + } wis::TextureDesc desc{ .format = wis::DataFormat::RGBA32Float, @@ -106,8 +113,9 @@ CreateWorkNode(wis::Adapter&& adapter) .usage = wis::TextureUsage::ShaderResource | wis::TextureUsage::HostCopy }; auto [res, texture] = node.extended_alloc.CreateGPUUploadTexture(node.allocator, desc, wis::TextureState::CopyDest, wis::MemoryFlags::DedicatedAllocation); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } wis::TextureRegion region{ .offset = { 0, 0, 0 }, @@ -115,8 +123,9 @@ CreateWorkNode(wis::Adapter&& adapter) .format = wis::DataFormat::RGBA32Float }; auto res2 = node.extended_alloc.WriteMemoryToSubresourceDirect(lut_data.data.get(), texture, wis::TextureState::CopyDest, region); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.lut = std::move(texture); } @@ -133,8 +142,9 @@ CreateWorkNode(wis::Adapter&& adapter) .usage = wis::TextureUsage::ShaderResource | wis::TextureUsage::HostCopy }; auto [res, texture] = node.extended_alloc.CreateGPUUploadTexture(node.allocator, desc, wis::TextureState::CopyDest, wis::MemoryFlags::DedicatedAllocation); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } wis::TextureRegion region{ .offset = { 0, 0, 0 }, @@ -142,8 +152,9 @@ CreateWorkNode(wis::Adapter&& adapter) .format = wis::DataFormat::RGBA8Unorm }; auto res2 = node.extended_alloc.WriteMemoryToSubresourceDirect(data.data.data(), texture, wis::TextureState::CopyDest, region); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.texture = std::move(texture); } @@ -157,8 +168,9 @@ CreateWorkNode(wis::Adapter&& adapter) .subresource_range = { 0, 1, 0, 1 } }; auto [res, srv] = node.work_device.CreateShaderResource(node.lut, desc); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.srv_lut = std::move(srv); } @@ -171,8 +183,9 @@ CreateWorkNode(wis::Adapter&& adapter) .subresource_range = { 0, 1, 0, 1 } }; auto [res, srv] = node.work_device.CreateShaderResource(node.texture, desc); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.srv = std::move(srv); } @@ -190,9 +203,10 @@ CreateWorkNode(wis::Adapter&& adapter) .mip_lod_bias = 0.0f, .comparison_op = wis::Compare::None, }; - auto [res, sampler] = node.work_device.CreateSampler(&sample_desc); - if (res.status != wis::Status::Ok) + auto [res, sampler] = node.work_device.CreateSampler(sample_desc); + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.sampler = std::move(sampler); } @@ -201,18 +215,22 @@ CreateWorkNode(wis::Adapter&& adapter) auto sv = LoadShader("lut.vs"); auto sp = LoadShader("lut_tetra.ps"); - if (!sv) + if (!sv) { return std::unexpected(sp.error()); - if (!sp) + } + if (!sp) { return std::unexpected(sp.error()); + } auto [res, vertex_shader] = node.work_device.CreateShader(sv.value().data(), sv.value().size()); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } auto [res2, pixel_shader] = node.work_device.CreateShader(sp.value().data(), sp.value().size()); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.vertex_shader = std::move(vertex_shader); node.pixel_shader = std::move(pixel_shader); @@ -258,8 +276,9 @@ CreateWorkNode(wis::Adapter&& adapter) }; auto [result, root] = node.desc_buffer_ext.CreateRootSignature(nullptr, 0, nullptr, 0, tables, sizeof(tables) / sizeof(tables[0])); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return std::unexpected(result.error); + } node.root = std::move(root); } @@ -274,25 +293,28 @@ CreateWorkNode(wis::Adapter&& adapter) }, .flags = wis::PipelineFlags::DescriptorBuffer, }; - auto [res2, hpipeline] = node.work_device.CreateGraphicsPipeline(&desc); - if (res2.status != wis::Status::Ok) + auto [res2, hpipeline] = node.work_device.CreateGraphicsPipeline(desc); + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } node.pipeline = std::move(hpipeline); } // Create Fence { auto [res, fence] = node.work_device.CreateFence(0); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.fence = std::move(fence); } // Create Command List { auto [res, cmd_list] = node.work_device.CreateCommandList(wis::QueueType::Graphics); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } node.cmd_list = std::move(cmd_list); } @@ -305,13 +327,15 @@ CreateWorkNode(wis::Adapter&& adapter) auto desc_size = wis::detail::aligned_size(inc_d * 2, al_d); auto [res, hdesc] = node.desc_buffer_ext.CreateDescriptorBuffer(wis::DescriptorHeapType::Descriptor, wis::DescriptorMemory::ShaderVisible, desc_size); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return std::unexpected(res.error); + } auto sampler_size = wis::detail::aligned_size(inc_s, al_s); auto [res2, hdesc2] = node.desc_buffer_ext.CreateDescriptorBuffer(wis::DescriptorHeapType::Sampler, wis::DescriptorMemory::ShaderVisible, sampler_size); - if (res2.status != wis::Status::Ok) + if (res2.status != wis::Status::Ok) { return std::unexpected(res2.error); + } // Set Descriptor Buffers hdesc.WriteShaderResource(0, 1, node.srv); @@ -374,14 +398,16 @@ void WorkNode::CreateOutputTexture(wis::Size2D frame) .usage = wis::TextureUsage::RenderTarget | wis::TextureUsage::CopySrc, }; auto [result, tex] = allocator.CreateTexture(desc); - if (result.status != wis::Status::Ok) + if (result.status != wis::Status::Ok) { return; + } // Create buffer { auto [r, b] = allocator.CreateReadbackBuffer(frame.width * frame.height * 4); - if (r.status != wis::Status::Ok) + if (r.status != wis::Status::Ok) { return; + } out_buffer = std::move(b); mapping = out_buffer.Map(); } @@ -392,8 +418,9 @@ void WorkNode::CreateOutputTexture(wis::Size2D frame) .format = wis::DataFormat::RGBA8Unorm, }; auto [res, rt] = work_device.CreateRenderTarget(tex, rt_desc); - if (res.status != wis::Status::Ok) + if (res.status != wis::Status::Ok) { return; + } render_target = std::move(rt); } diff --git a/examples/custom/multimon/work_node.h b/examples/custom/multimon/work_node.h index b68643c8..643eb18c 100644 --- a/examples/custom/multimon/work_node.h +++ b/examples/custom/multimon/work_node.h @@ -1,7 +1,7 @@ #pragma once #include -#include -#include +#include +#include #include struct WorkNode { @@ -12,8 +12,9 @@ struct WorkNode { WorkNode& operator=(WorkNode&&) noexcept = default; ~WorkNode() noexcept { - if (mapping) + if (mapping) { out_buffer.Unmap(); + } } public: diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt index f5213826..cdbf2c97 100644 --- a/generator/CMakeLists.txt +++ b/generator/CMakeLists.txt @@ -11,17 +11,15 @@ FetchContent_Declare( tinyxml2 GIT_REPOSITORY https://github.com/leethomason/tinyxml2.git GIT_TAG origin/master) - -set(tinyxml2_BUILD_TESTING - OFF - CACHE BOOL "" FORCE) FetchContent_GetProperties(tinyxml2) if(NOT tinyxml2_POPULATED) FetchContent_Populate(tinyxml2) # Disable tinyxml2 installation - add_subdirectory(${tinyxml2_SOURCE_DIR} ${tinyxml2_BINARY_DIR} - EXCLUDE_FROM_ALL) endif() +add_library( + re_tinyxml2 STATIC EXCLUDE_FROM_ALL ${tinyxml2_SOURCE_DIR}/tinyxml2.cpp + ${tinyxml2_SOURCE_DIR}/tinyxml2.h) +target_include_directories(re_tinyxml2 PUBLIC ${tinyxml2_SOURCE_DIR}) add_executable(${PROJECT_NAME}) target_sources(${PROJECT_NAME} PRIVATE entry_main.cpp generator.h generator.cpp) @@ -35,7 +33,7 @@ target_compile_definitions( "CPP_OUTPUT_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}/../wisdom/include/wisdom\"") target_include_directories( ${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../wisdom/include") -target_link_libraries(${PROJECT_NAME} PRIVATE tinyxml2::tinyxml2) +target_link_libraries(${PROJECT_NAME} PRIVATE re_tinyxml2) if(WISDOM_USE_FMT) find_package(fmt CONFIG QUIET) diff --git a/generator/generator.cpp b/generator/generator.cpp index 381312bc..797cd708 100644 --- a/generator/generator.cpp +++ b/generator/generator.cpp @@ -26,13 +26,15 @@ static inline InlineTypeInfo FindInlineType(std::string_view str, size_t initial { // Find caption enclosed in { } auto pos = str.find('{', initial); - if (pos == std::string_view::npos) + if (pos == std::string_view::npos) { return {}; + } auto end = str.find('}', pos); auto end_n = str.find('\n', pos); - if (end == std::string_view::npos || end_n < end) + if (end == std::string_view::npos || end_n < end) { return {}; + } std::string_view caption = str.substr(pos + 1, end - pos - 1); std::string_view type, value; @@ -49,10 +51,12 @@ static inline InlineTypeInfo FindInlineType(std::string_view str, size_t initial static ImplementedFor ImplCode(std::string_view impl) noexcept { - if (impl == "dx") + if (impl == "dx") { return ImplementedFor::DX12; - if (impl == "vk") + } + if (impl == "vk") { return ImplementedFor::Vulkan; + } return ImplementedFor::Both; } @@ -110,8 +114,9 @@ int Generator::GenerateCAPI() } for (auto& [name, h] : handle_map) { - if (!h.ext.empty()) + if (!h.ext.empty()) { continue; + } out_dx += MakeCHandle(h, impls[+ImplementedFor::DX12]); out_vk += MakeCHandle(h, impls[+ImplementedFor::Vulkan]); @@ -119,8 +124,9 @@ int Generator::GenerateCAPI() out_default_dx += MakeCHandleGeneric(h, impls[+ImplementedFor::DX12]); out_default_vk += MakeCHandleGeneric(h, impls[+ImplementedFor::Vulkan]); - if (h.functions.empty()) + if (h.functions.empty()) { continue; + } out_vk_methods += MakeCHandleMethods(h, impls[+ImplementedFor::Vulkan]) + '\n'; out_dx_methods += MakeCHandleMethods(h, impls[+ImplementedFor::DX12]) + '\n'; @@ -148,8 +154,9 @@ int Generator::GenerateCAPI() out_vk += out_vk_methods; for (auto* v : variants) { - if (v->implemented_for == Language::CPP) + if (v->implemented_for == Language::CPP) { continue; + } out_default_dx += MakeCVariantGeneric(*v, impls[+ImplementedFor::DX12]) + '\n'; out_default_vk += MakeCVariantGeneric(*v, impls[+ImplementedFor::Vulkan]) + '\n'; @@ -242,9 +249,9 @@ int Generator::GenerateCAPI() std::string output_vk_ext_impl; std::string output_dx_ext_impl; for (auto& [name, h] : extension_map) { - if (auto x = h.GetFile(ImplementedFor::DX12); x == h.GetFile(ImplementedFor::Vulkan)) + if (auto x = h.GetFile(ImplementedFor::DX12); x == h.GetFile(ImplementedFor::Vulkan)) { output_cpp_ext += wis::format("#include \"{}\"\n", x); - else { + } else { output_vk_ext_impl += wis::format("#include \"{}\"\n", h.GetFile(ImplementedFor::Vulkan)); output_dx_ext_impl += wis::format("#include \"{}\"\n", h.GetFile(ImplementedFor::DX12)); } @@ -268,22 +275,25 @@ int Generator::GenerateCAPI() auto output_cpp_abs = std::filesystem::absolute(output_path / "wisdom.cpp"); std::ofstream out_cpp(output_cpp_abs); - if (!out_cpp.is_open()) + if (!out_cpp.is_open()) { return 1; + } out_cpp << output_cpp; files.emplace_back(output_cpp_abs); auto output_cpp_ext_abs = std::filesystem::absolute(output_path / "wisdom_ext.inl"); std::ofstream out_cpp_ext(output_cpp_ext_abs); - if (!out_cpp_ext.is_open()) + if (!out_cpp_ext.is_open()) { return 1; + } out_cpp_ext << output_cpp_ext; files.emplace_back(output_cpp_ext_abs); auto output_abs = std::filesystem::absolute(output_path / "wisdom.h"); std::ofstream out(output_abs); - if (!out.is_open()) + if (!out.is_open()) { return 1; + } out << output; files.emplace_back(output_abs); return 0; @@ -292,7 +302,7 @@ int Generator::GenerateCPPAPI() { using namespace std::chrono; - std::string output_api = "//GENERATED\n#pragma once\n#include \n#include \n\n"; + std::string output_api = "//GENERATED\n#pragma once\n#include \n#include \n#include \n\n"; output_api += wis::format(documentation_header, WISDOM_VERSION); output_api += "\n*/\n\n"; @@ -326,9 +336,31 @@ struct ResultValue{ Result status; RetTy value; - constexpr ResultValue(RetTy value)noexcept :status(success), value(std::move(value)){} - constexpr ResultValue(Result status)noexcept :status(status){} - constexpr ResultValue(Result status, RetTy value)noexcept :status(status), value(std::move(value)){} + constexpr ResultValue() noexcept = default; + constexpr ResultValue(wis::Result status) noexcept + : status(status) + { + } + + template + requires std::is_member_function_pointer_v + constexpr ResultValue(Callable&& f, Callee* self, Args&&... args) noexcept + : value(std::invoke(f, self, status, std::forward(args)...)) + { + } + template + constexpr ResultValue(Callable && f, Args&&... args) noexcept + : value(f(status, std::forward(args)...)) + { + } + + template + static constexpr ResultValue from_member_func(Callable&& f, Callee* self, Args&&... args) noexcept + { + ResultValue rv; + rv.value = std::invoke(f, self, rv.status, std::forward(args)...); + return rv; + } }; template @@ -352,10 +384,11 @@ constexpr decltype(auto) get(ResultValue& rv) noexcept std::filesystem::create_directories(cpp_output_path_dx12); std::filesystem::create_directories(cpp_output_path_vulkan); - auto output_api_abs = std::filesystem::absolute(cpp_output_path_api / "api.h"); + auto output_api_abs = std::filesystem::absolute(cpp_output_path_api / "api.hpp"); std::ofstream out_api(output_api_abs); - if (!out_api.is_open()) + if (!out_api.is_open()) { return 1; + } out_api << output_api; files.emplace_back(output_api_abs); @@ -363,31 +396,35 @@ constexpr decltype(auto) get(ResultValue& rv) noexcept auto output_wisdom_vk_abs = std::filesystem::absolute(cpp_output_path / "wisdom_vk.hpp"); auto output_wisdom_abs = std::filesystem::absolute(cpp_output_path / "wisdom.hpp"); std::ofstream out_wisdom(output_wisdom_abs); - if (!out_wisdom.is_open()) + if (!out_wisdom.is_open()) { return 1; + } out_wisdom << GenerateCPPExportHeader(); files.emplace_back(output_wisdom_abs); std::ofstream out_wisdom_dx(output_wisdom_dx_abs); - if (!out_wisdom_dx.is_open()) + if (!out_wisdom_dx.is_open()) { return 1; + } out_wisdom_dx << GenerateCPPPlatformExportHeader(impls[+ImplementedFor::DX12]); files.emplace_back(output_wisdom_dx_abs); std::ofstream out_wisdom_vk(output_wisdom_vk_abs); - if (!out_wisdom_vk.is_open()) + if (!out_wisdom_vk.is_open()) { return 1; + } out_wisdom_vk << GenerateCPPPlatformExportHeader(impls[+ImplementedFor::Vulkan]); files.emplace_back(output_wisdom_vk_abs); auto output_dx_abs = std::filesystem::absolute(cpp_output_path_dx12 / "dx12_structs.hpp"); std::ofstream out_dxapi(output_dx_abs); - if (!out_dxapi.is_open()) + if (!out_dxapi.is_open()) { return 1; + } std::string dxapi = "#pragma once\n#include \n#include " - "\n#include " + "\n#include " "\n#include \n\nnamespace wis{\n"; for (auto i : variants) { if (i->this_type.empty()) { @@ -395,20 +432,22 @@ constexpr decltype(auto) get(ResultValue& rv) noexcept } } for (auto& c : cpp_conversion) { - if (c.impl == ImplementedFor::DX12) + if (c.impl == ImplementedFor::DX12) { dxapi += c.value; + } } out_dxapi << dxapi + "}\n"; files.emplace_back(output_dx_abs); auto output_vk_abs = std::filesystem::absolute(cpp_output_path_vulkan / "vk_structs.hpp"); std::ofstream out_vkapi(output_vk_abs); - if (!out_vkapi.is_open()) + if (!out_vkapi.is_open()) { return 1; + } std::string vkapi = "#pragma once\n#include \n#include " - "\n#include " + "\n#include " "\n\nnamespace wis{\n"; for (auto i : variants) { if (i->this_type.empty()) { @@ -416,8 +455,9 @@ constexpr decltype(auto) get(ResultValue& rv) noexcept } } for (auto& c : cpp_conversion) { - if (c.impl == ImplementedFor::Vulkan) + if (c.impl == ImplementedFor::Vulkan) { vkapi += c.value; + } } out_vkapi << vkapi + "}\n"; @@ -469,8 +509,9 @@ int Generator::GenerateCPPInlineDoc() }; for (auto& [k, h] : handle_map) { - if (h.functions.empty()) + if (h.functions.empty()) { continue; + } if (!h.ext.empty()) { auto ext_folder = extension_map[h.ext].ext_folder; @@ -494,8 +535,9 @@ int Generator::GenerateCPPInlineDoc() } for (auto& [k, v] : extension_map) { - if (v.functions.empty()) + if (v.functions.empty()) { continue; + } if (auto file = v.GetFile(ImplementedFor::DX12); !file.empty()) { write_doc(v, file, impls[+ImplementedFor::DX12], std::filesystem::path{ ext_dir } / v.ext_folder); @@ -508,8 +550,9 @@ int Generator::GenerateCPPInlineDoc() // mt? for (auto& [p, d] : file_contents) { std::ofstream out(p); - if (!out.is_open()) + if (!out.is_open()) { return 1; + } out << d << std::flush; } @@ -613,8 +656,9 @@ std::string Generator::GenerateCPPPlatformTypedefs(std::string_view impl) output += wis::format("inline constexpr wis::ShaderIntermediate shader_intermediate = wis::ShaderIntermediate::{};\n\n", impl == "VK" ? "SPIRV" : "DXIL"); for (auto& [name, h] : handle_map) { - if (!h.ext.empty()) + if (!h.ext.empty()) { continue; + } output += wis::format("using {} = {}{};\n", name, impl, name); } @@ -622,14 +666,16 @@ std::string Generator::GenerateCPPPlatformTypedefs(std::string_view impl) output += k_delimiter; for (auto& f : cpp_funcs) { - output += MakeCPPFunctionGenericDecl(*f, impl) + '\n'; + output += MakeCPPFunctionGenericDecl(*f, impl, true) + '\n'; + output += MakeCPPFunctionGenericDecl(*f, impl, false) + '\n'; } output += k_delimiter; for (auto& v : variants) { - if (v->ext.empty()) + if (v->ext.empty()) { output += wis::format("using {} = {}{};\n", v->name, impl, v->name); + } } return output + "}\n"; @@ -701,8 +747,13 @@ std::string Generator::GenerateCPPPlatformExportHeader(std::string_view impl) // Generate platform funcs for (auto& f : functions) { - output += wis::format("{}{{ return wis::Impl{}; }}\n", MakeCPPFunctionProto(*f, impl, "inline"), - MakeCPPFunctionCall(*f, impl)); + std::string_view prefix = f->return_type.has_result ? "[[nodiscard]] inline" : "inline"; + + output += wis::format("{}{{ return wis::Impl{}; }}\n", MakeCPPFunctionProto(*f, impl, prefix, true, true, true), + MakeCPPFunctionCall(*f, impl, true)); + + output += wis::format("{} noexcept{{\n {} {};\n}}\n", MakeCPPFunctionProto(*f, impl, prefix, true, true, false), + !f->return_type.IsVoid() ? "return" : "", MakeCPPRVFunctionCall(*f, wis::format("wis::Impl{}{}", impl, ""), impl)); } output += k_delimiter; @@ -718,23 +769,29 @@ std::string Generator::GenerateCPPPlatformExportHeader(std::string_view impl) void Generator::ParseFile(tinyxml2::XMLDocument& doc) { auto* root = doc.FirstChildElement("registry"); - if (!root) + if (!root) { throw std::runtime_error("Failed to load root"); + } - if (auto* include = root->FirstChildElement("includes")) + if (auto* include = root->FirstChildElement("includes")) { ParseIncludes(include); + } - if (auto* handles = root->FirstChildElement("handles")) + if (auto* handles = root->FirstChildElement("handles")) { ParseHandles(handles); + } - if (auto* types = root->FirstChildElement("types")) + if (auto* types = root->FirstChildElement("types")) { ParseTypes(types); + } - if (auto* funcs = root->FirstChildElement("functions")) + if (auto* funcs = root->FirstChildElement("functions")) { ParseFunctions(funcs); + } - if (auto* exts = root->FirstChildElement("extensions")) + if (auto* exts = root->FirstChildElement("extensions")) { ParseExtensions(exts); + } } void Generator::ParseTypes(tinyxml2::XMLElement* types, std::string_view extension) @@ -766,8 +823,9 @@ void Generator::ParseIncludes(tinyxml2::XMLElement* includes) if (std::filesystem::exists(absolute) && !this->includes.contains(absolute)) { auto& doc = this->includes[absolute]; - if (doc.LoadFile(absolute.string().c_str()) != tinyxml2::XMLError::XML_SUCCESS) + if (doc.LoadFile(absolute.string().c_str()) != tinyxml2::XMLError::XML_SUCCESS) { throw std::runtime_error("Failed to load include file"); + } ParseFile(doc); } } @@ -778,24 +836,29 @@ WisReturnType Generator::ParseFunctionReturn(tinyxml2::XMLElement* func) WisReturnType ret; if (auto* param = func->FirstChildElement("ret")) { - if (auto* res = param->FindAttribute("result")) + if (auto* res = param->FindAttribute("result")) { ret.has_result = true; + } auto* type = param->FindAttribute("type"); - if (!type) + if (!type) { return ret; // No return type + } ret.type = type->Value(); ret.type_info = GetTypeInfo(type->Value()); - if (auto* name = param->FindAttribute("name")) + if (auto* name = param->FindAttribute("name")) { ret.opt_name = name->Value(); + } - if (auto* mod = param->FindAttribute("mod")) + if (auto* mod = param->FindAttribute("mod")) { ret.modifier = mod->Value(); + } - if (auto* doc = param->FindAttribute("doc")) + if (auto* doc = param->FindAttribute("doc")) { ret.doc = doc->Value(); + } } return ret; } @@ -813,14 +876,17 @@ std::vector Generator::ParseFunctionArgs(tinyxml2::XMLElem p.name = name; p.type_info = GetTypeInfo(type); - if (auto* mod = param->FindAttribute("mod")) + if (auto* mod = param->FindAttribute("mod")) { p.modifier = mod->Value(); + } - if (auto* def = param->FindAttribute("default")) + if (auto* def = param->FindAttribute("default")) { p.default_value = def->Value(); + } - if (auto* doc = param->FindAttribute("doc")) + if (auto* doc = param->FindAttribute("doc")) { p.doc = doc->Value(); + } if (auto replace = param->FirstChildElement("replace")) { using namespace std::string_view_literals; @@ -837,17 +903,21 @@ std::vector Generator::ParseFunctionArgs(tinyxml2::XMLElem rval.replace_for = Language::CPP; } - if (auto* doc = replace->FindAttribute("doc")) + if (auto* doc = replace->FindAttribute("doc")) { rval.doc = doc->Value(); + } - if (auto* mod = replace->FindAttribute("mod")) + if (auto* mod = replace->FindAttribute("mod")) { rval.modifier = mod->Value(); + } - if (auto* def = replace->FindAttribute("default")) + if (auto* def = replace->FindAttribute("default")) { rval.default_value = def->Value(); + } - if (auto* name = replace->FindAttribute("name")) + if (auto* name = replace->FindAttribute("name")) { rval.name = name->Value(); + } } } return ret; @@ -871,14 +941,16 @@ void Generator::ParseFunctions(tinyxml2::XMLElement* type) if (ret) { ref.this_type = ret->Value(); ref.this_type_info = GetTypeInfo(ref.this_type); - if (ref.this_type_info == TypeInfo::Handle) + if (ref.this_type_info == TypeInfo::Handle) { handle_map[ref.this_type].functions.emplace_back(xkey); - else if (ref.this_type_info == TypeInfo::ExtHandle) + } else if (ref.this_type_info == TypeInfo::ExtHandle) { extension_map[ref.this_type].functions.emplace_back(xkey); + } } - if (auto* doc = func->FindAttribute("doc")) + if (auto* doc = func->FindAttribute("doc")) { ref.doc = doc->Value(); + } ref.return_type = ParseFunctionReturn(func); ref.parameters = ParseFunctionArgs(func); @@ -919,11 +991,13 @@ void Generator::ParseExtensions(tinyxml2::XMLElement* extensions) ref.name = name; - if (auto* doc = ext->FindAttribute("doc")) + if (auto* doc = ext->FindAttribute("doc")) { ref.doc = doc->Value(); + } - if (auto* ext_folder = ext->FindAttribute("folder")) + if (auto* ext_folder = ext->FindAttribute("folder")) { ref.ext_folder = ext_folder->Value(); + } for (auto* impl = ext->FirstChildElement("file"); impl; impl = impl->NextSiblingElement("file")) { @@ -975,11 +1049,13 @@ void Generator::ParseHandles(tinyxml2::XMLElement* types, std::string_view exten ref.name = name; ref.ext = extension; - if (!extension.empty()) + if (!extension.empty()) { extension_map[extension].handles.emplace_back(name); + } - if (auto* doc = type->FindAttribute("doc")) + if (auto* doc = type->FindAttribute("doc")) { ref.doc = doc->Value(); + } for (auto* impl = type->FirstChildElement("file"); impl; impl = impl->NextSiblingElement("file")) { @@ -999,8 +1075,9 @@ void Generator::ParseStruct(tinyxml2::XMLElement& type) structs.emplace_back(&ref); ref.name = name; - if (auto* size = type.FindAttribute("doc")) + if (auto* size = type.FindAttribute("doc")) { ref.doc = size->Value(); + } for (auto* member = type.FirstChildElement("member"); member; member = member->NextSiblingElement("member")) { @@ -1041,11 +1118,13 @@ void Generator::ParseEnum(tinyxml2::XMLElement& type) auto& ref = enum_map[name]; ref.name = name; - if (auto* size = type.FindAttribute("type")) + if (auto* size = type.FindAttribute("type")) { ref.type = size->Value(); + } - if (auto* size = type.FindAttribute("doc")) + if (auto* size = type.FindAttribute("doc")) { ref.doc = size->Value(); + } for (auto* impl_type = type.FirstChildElement("impl_type"); impl_type; impl_type = impl_type->NextSiblingElement("impl_type")) { @@ -1056,8 +1135,9 @@ void Generator::ParseEnum(tinyxml2::XMLElement& type) ref.doc_translates += wis::format("Translates to {} for {} implementation.\n", impl_name, impl_for); std::string_view def_value = "{}"; - if (auto xdefault = impl_type->FindAttribute("default")) + if (auto xdefault = impl_type->FindAttribute("default")) { def_value = xdefault->Value(); + } if (auto direct = impl_type->FindAttribute("direct")) { auto cvt = wis::format("inline constexpr {} convert_{}({} value) noexcept {{\n " @@ -1077,11 +1157,13 @@ void Generator::ParseEnum(tinyxml2::XMLElement& type) m.name = member->FindAttribute("name")->Value(); m.value = std::stoll(member->FindAttribute("value")->Value()); - if (auto* impl = member->FindAttribute("impl")) + if (auto* impl = member->FindAttribute("impl")) { m.impl = ImplCode(impl->Value()); + } - if (auto* doc = member->FindAttribute("doc")) + if (auto* doc = member->FindAttribute("doc")) { m.doc = doc->Value(); + } for (auto* impl = member->FirstChildElement("impl"); impl; impl = impl->NextSiblingElement("impl")) { @@ -1104,11 +1186,13 @@ void Generator::ParseBitmask(tinyxml2::XMLElement& type) auto& ref = bitmask_map[name]; ref.name = name; - if (auto* size = type.FindAttribute("type")) + if (auto* size = type.FindAttribute("type")) { ref.type = size->Value(); + } - if (auto* size = type.FindAttribute("doc")) + if (auto* size = type.FindAttribute("doc")) { ref.doc = size->Value(); + } for (auto* impl_type = type.FirstChildElement("impl_type"); impl_type; impl_type = impl_type->NextSiblingElement("impl_type")) { @@ -1119,8 +1203,9 @@ void Generator::ParseBitmask(tinyxml2::XMLElement& type) ref.doc_translates += wis::format("Translates to {} for {} implementation.\n", impl_name, impl_for); std::string_view def_value = "{}"; - if (auto xdefault = impl_type->FindAttribute("default")) + if (auto xdefault = impl_type->FindAttribute("default")) { def_value = xdefault->Value(); + } if (auto direct = impl_type->FindAttribute("direct")) { auto cvt = wis::format("inline constexpr {} convert_{}({} value) noexcept {{\n " @@ -1139,14 +1224,16 @@ void Generator::ParseBitmask(tinyxml2::XMLElement& type) auto& m = ref.values.emplace_back(); m.name = member->FindAttribute("name")->Value(); - if (auto* impl = member->FindAttribute("impl")) + if (auto* impl = member->FindAttribute("impl")) { m.impl = ImplCode(impl->Value()); + } auto* value = member->FindAttribute("value"); auto* bit = member->FindAttribute("bit"); - if (auto* doc = member->FindAttribute("doc")) + if (auto* doc = member->FindAttribute("doc")) { m.doc = doc->Value(); + } if (value) { m.value = std::stoull(value->Value()); @@ -1178,8 +1265,9 @@ void Generator::ParseDelegate(tinyxml2::XMLElement* type) ref.name = name; ref.parameters = ParseFunctionArgs(type); - if (auto* size = type->FindAttribute("doc")) + if (auto* size = type->FindAttribute("doc")) { ref.doc = size->Value(); + } } void Generator::ParseVariant(tinyxml2::XMLElement& type, std::string_view extension) @@ -1194,14 +1282,16 @@ void Generator::ParseVariant(tinyxml2::XMLElement& type, std::string_view extens ref.this_type = this_t->Value(); } - if (auto* size = type.FindAttribute("doc")) + if (auto* size = type.FindAttribute("doc")) { ref.doc = size->Value(); + } if (auto* mod = type.FindAttribute("mod")) { - if (std::string_view(mod->Value()) == "cpp-only") + if (std::string_view(mod->Value()) == "cpp-only") { ref.implemented_for = Language::CPP; - else if (std::string_view(mod->Value()) == "c-only") + } else if (std::string_view(mod->Value()) == "c-only") { ref.implemented_for = Language::C; + } } for (auto* impl = type.FirstChildElement("impl"); impl; impl = impl->NextSiblingElement("impl")) { @@ -1239,20 +1329,23 @@ void Generator::ParseVariant(tinyxml2::XMLElement& type, std::string_view extens std::string Generator::FinalizeCDocumentation(std::string doc, std::string_view this_type, std::string_view impl) { - if (doc.empty()) + if (doc.empty()) { return doc; + } size_t pos = 0; std::string_view this_type_view = this_type; while (true) { auto&& [type, value, first, last] = FindInlineType(doc, pos); - if (type.empty() && value.empty()) + if (type.empty() && value.empty()) { break; + } // Replace with this_type - if (!type.empty()) + if (!type.empty()) { this_type_view = type; + } std::string replacement; @@ -1288,20 +1381,23 @@ std::string Generator::FinalizeCDocumentation(std::string doc, std::string_view } std::string Generator::FinalizeCPPDocumentation(std::string doc, std::string_view this_type, std::string_view impl) { - if (doc.empty()) + if (doc.empty()) { return doc; + } size_t pos = 0; std::string_view this_type_view = this_type; while (true) { auto&& [type, value, first, last] = FindInlineType(doc, pos); - if (type.empty() && value.empty()) + if (type.empty() && value.empty()) { break; + } // Replace with this_type - if (!type.empty()) + if (!type.empty()) { this_type_view = type; + } std::string replacement; @@ -1379,8 +1475,9 @@ std::pair Generator::MakeCVariant(const WisVariant& s) { using namespace std::string_literals; - if (s.implemented_for == Language::CPP) + if (s.implemented_for == Language::CPP) { return {}; + } std::string st_decls; @@ -1440,10 +1537,11 @@ std::pair Generator::MakeCVariant(const WisVariant& s) vk += make_impl(s, i, impls[2]); return { std::move(dx), std::move(vk) }; } - if (+i.impl == 1) + if (+i.impl == 1) { dx += make_impl(s, i, impls[+i.impl]); - else if (+i.impl == 2) + } else if (+i.impl == 2) { vk += make_impl(s, i, impls[+i.impl]); + } } return { dx, vk }; } @@ -1771,8 +1869,9 @@ std::string Generator::MakeCFunctionCall(const WisFunction& func, std::string_vi } std::string Generator::MakeCFunctionImpl(const WisFunction& func, std::string_view prefix, std::string_view impl) { - if (func.custom_impl) + if (func.custom_impl) { return ""; + } std::string output; @@ -2124,12 +2223,12 @@ std::string Generator::MakeCVariantGeneric(const WisVariant& s, std::string_view #pragma endregion #pragma region C++ API -std::string Generator::MakeCPPFunctionGenericDecl(const WisFunction& func, std::string_view impl) +std::string Generator::MakeCPPFunctionGenericDecl(const WisFunction& func, std::string_view impl, bool explicit_result) { - return wis::format("{}{{ return {}; }}", MakeCPPFunctionProto(func, "", "inline"), - MakeCPPFunctionCall(func, impl)); + return wis::format("{}{{ return {}; }}", MakeCPPFunctionProto(func, "", "inline", true, true, explicit_result), + MakeCPPFunctionCall(func, impl, explicit_result)); } -std::string Generator::MakeCPPFunctionProto(const WisFunction& func, std::string_view impl, std::string_view pre_decl, bool enable_doc, bool impl_on_fdecl) +std::string Generator::MakeCPPFunctionProto(const WisFunction& func, std::string_view impl, std::string_view pre_decl, bool enable_doc, bool impl_on_fdecl, bool explicit_result) { std::string args; std::string return_t; @@ -2139,6 +2238,10 @@ std::string Generator::MakeCPPFunctionProto(const WisFunction& func, std::string doc = wis::format("/**\n@brief {}\n", func.doc); } + if (explicit_result && func.return_type.has_result && !func.return_type.type.empty()) { + args += "wis::Result& result, "; + } + // Arguments for (auto& arg : func.parameters) { if (arg.replaced && arg.replaced->replace_for == Language::CPP) { @@ -2162,9 +2265,11 @@ std::string Generator::MakeCPPFunctionProto(const WisFunction& func, std::string if (func.return_type.type == "") { return_t = func.return_type.has_result ? GetCPPFullTypename("Result") : "void"; } else if (func.return_type.has_result) { - // make wis::ResultValue return type + return_t = explicit_result + ? wis::format("{}", GetCPPFullTypename(func.return_type.type, impl)) + : wis::format("wis::ResultValue<{}>", GetCPPFullTypename(func.return_type.type, impl)); + doc += wis::format("@return {}\n", func.return_type.doc); - return_t = wis::format("wis::ResultValue<{}>", GetCPPFullTypename(func.return_type.type, impl)); } else { WisFunctionParameter res{ .type_info = func.return_type.type_info, @@ -2199,10 +2304,14 @@ std::string Generator::MakeCPPFunctionDecl(const WisFunction& func, std::string_ { return MakeCPPFunctionProto(func, impl, pre_decl) + ";\n"; } -std::string Generator::MakeCPPFunctionCall(const WisFunction& func, std::string_view impl) +std::string Generator::MakeCPPFunctionCall(const WisFunction& func, std::string_view impl, bool explicit_result) { std::string args; + if (explicit_result && func.return_type.IsRV()) { + args += "result, "; + } + // Arguments for (auto& arg : func.parameters) { @@ -2221,6 +2330,34 @@ std::string Generator::MakeCPPFunctionCall(const WisFunction& func, std::string_ return wis::format("{}{}({})", impl, func.name, args); } + +std::string Generator::MakeCPPRVFunctionCall(const WisFunction& func, std::string_view impl, std::string_view class_impl) +{ + // return wis::ResultValue{ + // &ImplDX12Factory::GetAdapter, this, index, preference + // }; + + std::string args; + + // Arguments + for (auto& arg : func.parameters) { + + if (arg.type_info == TypeInfo::Handle && arg.modifier.empty()) { + args += wis::format("std::move({}), ", arg.name); + } else { + args += std::string(arg.name) + ", "; + } + } + + // Remove trailing ", " + if (args.ends_with(", ")) { + args.pop_back(); + args.pop_back(); + } + return func.this_type.empty() + ? wis::format("wis::ResultValue<{}>{{&{}{},{}}}", GetCPPFullTypename(func.return_type.type, class_impl), impl, func.name, args) + : wis::format("wis::ResultValue<{}>{{&{}{},this,{}}}", GetCPPFullTypename(func.return_type.type, class_impl), impl, func.name, args); +} std::string Generator::MakeCPPDelegate(const WisFunction& func) { std::string_view impl = ""; @@ -2288,7 +2425,7 @@ std::string Generator::MakeCPPHandle(const WisHandle& s, std::string_view impl) ReplaceAll(doc, "\n", "\n * "); } - std::string head = wis::format("{}\class {}{} : public wis::Impl{}{}", doc, impl, s.name, impl, s.name); + std::string head = wis::format("{}\nclass {}{} : public wis::Impl{}{}", doc, impl, s.name, impl, s.name); std::string ctor = wis::format("public:\n using wis::Impl{}{}::Impl{}{};", impl, s.name, impl, s.name); std::string funcs = "public:\n"; @@ -2298,8 +2435,15 @@ std::string Generator::MakeCPPHandle(const WisHandle& s, std::string_view impl) continue; } - funcs += wis::format("{}{} noexcept{{\n {} {};\n}}\n", MakeCPPFunctionProto(func, impl, func.return_type.has_result ? "[[nodiscard]] inline" : "inline", true, false), - func.const_func ? "const" : "", !func.return_type.IsVoid() ? "return" : "", MakeCPPFunctionCall(func, wis::format("wis::Impl{}{}::", impl, s.name))); + if (func.return_type.IsRV()) { + funcs += wis::format("{}{} noexcept{{\n {} {};\n}}\n", MakeCPPFunctionProto(func, impl, func.return_type.has_result ? "[[nodiscard]] inline" : "inline", true, false, true), + func.const_func ? "const" : "", !func.return_type.IsVoid() ? "return" : "", MakeCPPFunctionCall(func, wis::format("wis::Impl{}{}::", impl, s.name), true)); + funcs += wis::format("{}{} noexcept{{\n {} {};\n}}\n", MakeCPPFunctionProto(func, impl, func.return_type.has_result ? "[[nodiscard]] inline" : "inline", true, false, false), + func.const_func ? "const" : "", !func.return_type.IsVoid() ? "return" : "", MakeCPPRVFunctionCall(func, wis::format("wis::Impl{}{}::", impl, s.name), impl)); + } else { + funcs += wis::format("{}{} noexcept{{\n {} {};\n}}\n", MakeCPPFunctionProto(func, impl, func.return_type.has_result ? "[[nodiscard]] inline" : "inline", true, false), + func.const_func ? "const" : "", !func.return_type.IsVoid() ? "return" : "", MakeCPPFunctionCall(func, wis::format("wis::Impl{}{}::", impl, s.name))); + } } return wis::format("{} {{\n{}\n{}\n}};\n", head, ctor, funcs); @@ -2308,67 +2452,87 @@ std::string Generator::MakeCPPHandle(const WisHandle& s, std::string_view impl) std::string Generator::GetCFullTypename(std::string_view type, std::string_view impl) { - if (type.empty()) + if (type.empty()) { return ""; + } - if (auto it = standard_types.find(type); it != standard_types.end()) + if (auto it = standard_types.find(type); it != standard_types.end()) { return std::string(it->second); + } - if (auto it = enum_map.find(type); it != enum_map.end()) + if (auto it = enum_map.find(type); it != enum_map.end()) { return "Wis" + std::string(type); + } - if (auto it = bitmask_map.find(type); it != bitmask_map.end()) + if (auto it = bitmask_map.find(type); it != bitmask_map.end()) { return "Wis" + std::string(type); + } - if (auto it = variant_map.find(type); it != variant_map.end()) + if (auto it = variant_map.find(type); it != variant_map.end()) { return std::string(impl) + std::string(type); + } - if (auto it = struct_map.find(type); it != struct_map.end()) + if (auto it = struct_map.find(type); it != struct_map.end()) { return "Wis" + std::string(type); + } - if (auto it = handle_map.find(type); it != handle_map.end()) + if (auto it = handle_map.find(type); it != handle_map.end()) { return std::string(impl) + std::string(type); - if (auto it = extension_map.find(type); it != extension_map.end()) + } + if (auto it = extension_map.find(type); it != extension_map.end()) { return std::string(impl) + std::string(type); + } - if (auto it = delegate_map.find(type); it != delegate_map.end()) + if (auto it = delegate_map.find(type); it != delegate_map.end()) { return std::string(type); + } - if (auto it = function_map.find(std::string(type)); it != function_map.end()) + if (auto it = function_map.find(std::string(type)); it != function_map.end()) { return std::string(impl) + std::string(type); + } return ""; } std::string Generator::GetCPPFullTypename(std::string_view type, std::string_view impl) { - if (type.empty()) + if (type.empty()) { return ""; + } - if (auto it = standard_types.find(type); it != standard_types.end()) + if (auto it = standard_types.find(type); it != standard_types.end()) { return std::string(it->second); + } - if (auto it = enum_map.find(type); it != enum_map.end()) + if (auto it = enum_map.find(type); it != enum_map.end()) { return "wis::" + std::string(type); + } - if (auto it = bitmask_map.find(type); it != bitmask_map.end()) + if (auto it = bitmask_map.find(type); it != bitmask_map.end()) { return "wis::" + std::string(type); + } - if (auto it = variant_map.find(type); it != variant_map.end()) + if (auto it = variant_map.find(type); it != variant_map.end()) { return "wis::" + std::string(impl) + std::string(type); + } - if (auto it = struct_map.find(type); it != struct_map.end()) + if (auto it = struct_map.find(type); it != struct_map.end()) { return "wis::" + std::string(type); + } - if (auto it = handle_map.find(type); it != handle_map.end()) + if (auto it = handle_map.find(type); it != handle_map.end()) { return "wis::" + std::string(impl) + std::string(type); - if (auto it = extension_map.find(type); it != extension_map.end()) + } + if (auto it = extension_map.find(type); it != extension_map.end()) { return "wis::" + std::string(impl) + std::string(type); + } - if (auto it = delegate_map.find(type); it != delegate_map.end()) + if (auto it = delegate_map.find(type); it != delegate_map.end()) { return "wis::" + std::string(type); + } - if (auto it = function_map.find(std::string(type)); it != function_map.end()) + if (auto it = function_map.find(std::string(type)); it != function_map.end()) { return "wis::" + std::string(impl) + std::string(type); + } return ""; } @@ -2487,32 +2651,41 @@ std::string Generator::ConvertToCType(const WisFunctionParameter& arg, std::stri TypeInfo Generator::GetTypeInfo(std::string_view type) { - if (type == "Result") + if (type == "Result") { return TypeInfo::Result; + } - if (standard_types.contains(type)) + if (standard_types.contains(type)) { return TypeInfo::Regular; + } - if (enum_map.contains(type)) + if (enum_map.contains(type)) { return TypeInfo::Enum; + } - if (bitmask_map.contains(type)) + if (bitmask_map.contains(type)) { return TypeInfo::Bitmask; + } - if (variant_map.contains(type)) + if (variant_map.contains(type)) { return TypeInfo::Variant; + } - if (struct_map.contains(type)) + if (struct_map.contains(type)) { return TypeInfo::Struct; + } - if (handle_map.contains(type)) + if (handle_map.contains(type)) { return TypeInfo::Handle; + } - if (extension_map.contains(type)) + if (extension_map.contains(type)) { return TypeInfo::ExtHandle; + } - if (delegate_map.contains(type)) + if (delegate_map.contains(type)) { return TypeInfo::Delegate; + } return TypeInfo::None; } diff --git a/generator/generator.h b/generator/generator.h index fa257d27..25cd43ed 100644 --- a/generator/generator.h +++ b/generator/generator.h @@ -7,6 +7,8 @@ #include #include #include +#include +#include static constexpr std::string_view documentation_header = R"(/** \mainpage Wisdom API Documentation @@ -38,8 +40,9 @@ struct WisEnum { std::optional HasValue(std::string_view name) const noexcept { - if (name.empty()) + if (name.empty()) { return {}; + } auto enum_value = std::find_if(values.begin(), values.end(), [&](auto& v) { return v.name == name; @@ -68,8 +71,9 @@ struct WisBitmask { std::optional HasValue(std::string_view name) const noexcept { - if (name.empty()) + if (name.empty()) { return {}; + } auto enum_value = std::find_if(values.begin(), values.end(), [&](auto& v) { return v.name == name; @@ -98,8 +102,9 @@ struct WisStruct { std::vector members; std::optional HasValue(std::string_view name) const noexcept { - if (name.empty()) + if (name.empty()) { return {}; + } auto enum_value = std::find_if(members.begin(), members.end(), [&](auto& v) { return v.name == name; @@ -168,6 +173,10 @@ struct WisReturnType { { return type.empty() && !has_result; } + bool IsRV() const noexcept + { + return has_result && !type.empty(); + } }; struct WisFunction { std::string_view name; @@ -183,8 +192,9 @@ struct WisFunction { std::optional HasValue(std::string_view name) const noexcept { - if (name.empty()) + if (name.empty()) { return {}; + } auto enum_value = std::find_if(parameters.begin(), parameters.end(), [&](auto& v) { return v.name == name; }); @@ -202,33 +212,39 @@ struct WisHandle { void AddFile(std::string_view file, ImplementedFor impl) noexcept { - if (impl & ImplementedFor::DX12) + if (impl & ImplementedFor::DX12) { files[0] = file; - if (impl & ImplementedFor::Vulkan) + } + if (impl & ImplementedFor::Vulkan) { files[1] = file; + } } std::string_view GetFile(ImplementedFor impl) const noexcept { - if (impl & ImplementedFor::DX12) + if (impl & ImplementedFor::DX12) { return files[0]; - if (impl & ImplementedFor::Vulkan) + } + if (impl & ImplementedFor::Vulkan) { return files[1]; + } return ""; } std::optional HasValue(std::string_view name, const std::unordered_map& function_map) const noexcept { - if (name.empty()) + if (name.empty()) { return {}; + } auto enum_value = std::find_if(functions.begin(), functions.end(), [&](auto& v) { return v == name; }); - if (enum_value == functions.end()) + if (enum_value == functions.end()) { return {}; + } return function_map.at(*enum_value); } @@ -337,10 +353,11 @@ class Generator #pragma region CPP API // Function generation - std::string MakeCPPFunctionGenericDecl(const WisFunction& func, std::string_view impl); - std::string MakeCPPFunctionProto(const WisFunction& func, std::string_view impl, std::string_view pre_decl = "WISDOM_API", bool doc = true, bool impl_on_fdecl = true); + std::string MakeCPPFunctionGenericDecl(const WisFunction& func, std::string_view impl, bool explicit_result); + std::string MakeCPPFunctionProto(const WisFunction& func, std::string_view impl, std::string_view pre_decl = "WISDOM_API", bool doc = true, bool impl_on_fdecl = true, bool explicit_result = false); std::string MakeCPPFunctionDecl(const WisFunction& func, std::string_view impl, std::string_view pre_decl = "WISDOM_API"); - std::string MakeCPPFunctionCall(const WisFunction& func, std::string_view impl); + std::string MakeCPPFunctionCall(const WisFunction& func, std::string_view impl, bool explicit_result = false); + std::string MakeCPPRVFunctionCall(const WisFunction& func, std::string_view impl, std::string_view class_impl); std::string MakeCPPDelegate(const WisFunction& s); // Handle generation diff --git a/tests/basic/copy_tests.cpp b/tests/basic/copy_tests.cpp index 2527b0b8..3e5f2cea 100644 --- a/tests/basic/copy_tests.cpp +++ b/tests/basic/copy_tests.cpp @@ -1,8 +1,8 @@ #include -#include +#include #include -#include -#include +#include +#include #include struct LogProvider : public wis::LogLayer { diff --git a/tests/basic/extension_tests.cpp b/tests/basic/extension_tests.cpp index 43ae72bf..77606468 100644 --- a/tests/basic/extension_tests.cpp +++ b/tests/basic/extension_tests.cpp @@ -1,8 +1,8 @@ #include -#include +#include #include -#include -#include +#include +#include #include struct LogProvider3 : public wis::LogLayer { diff --git a/tests/basic/relaxed_destruction_order.cpp b/tests/basic/relaxed_destruction_order.cpp index e610144f..7f2f2dd1 100644 --- a/tests/basic/relaxed_destruction_order.cpp +++ b/tests/basic/relaxed_destruction_order.cpp @@ -1,7 +1,7 @@ #include -#include +#include #include -#include +#include #include struct LogProvider : public wis::LogLayer { diff --git a/tests/basic/vulkan_tests.cpp b/tests/basic/vulkan_tests.cpp index 44152c87..9306ba4a 100644 --- a/tests/basic/vulkan_tests.cpp +++ b/tests/basic/vulkan_tests.cpp @@ -1,8 +1,8 @@ #include -#include -#include +#include +#include #include -#include +#include #include struct LogProvider2 : public wis::LogLayer { diff --git a/tests/manual/extended_allocation/test.cpp b/tests/manual/extended_allocation/test.cpp index f6f8c1b0..f02e4ac7 100644 --- a/tests/manual/extended_allocation/test.cpp +++ b/tests/manual/extended_allocation/test.cpp @@ -1,7 +1,7 @@ #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/wisdom/extensions/debug_info/CMakeLists.txt b/wisdom/extensions/debug_info/CMakeLists.txt index f946656c..0242ef28 100644 --- a/wisdom/extensions/debug_info/CMakeLists.txt +++ b/wisdom/extensions/debug_info/CMakeLists.txt @@ -11,7 +11,7 @@ target_include_directories( $) if(WISDOM_BUILD_BINARIES) - add_library(wisdom-debug STATIC "wisdom/wisdom_debug.h" + add_library(wisdom-debug STATIC "wisdom/wisdom_debug.hpp" "wisdom/wisdom_debug.cpp") add_library(wis::debug ALIAS wisdom-debug) target_link_libraries(wisdom-debug PUBLIC wis::wisdom) diff --git a/wisdom/extensions/debug_info/wisdom/wisdom_debug.cpp b/wisdom/extensions/debug_info/wisdom/wisdom_debug.cpp index 846dc240..3f04fae1 100644 --- a/wisdom/extensions/debug_info/wisdom/wisdom_debug.cpp +++ b/wisdom/extensions/debug_info/wisdom/wisdom_debug.cpp @@ -1,10 +1,10 @@ #ifndef WIS_WISDOM_DEBUG_CPP #define WIS_WISDOM_DEBUG_CPP -#include +#include #if defined(WISDOM_DX12) -wis::ResultValue -wis::ImplDX12DebugExtension::CreateDebugMessenger(wis::DebugCallback callback, void* user_data) const noexcept +wis::DX12DebugMessenger +wis::ImplDX12DebugExtension::CreateDebugMessenger(wis::Result& result, wis::DebugCallback callback, void* user_data) const noexcept { return wis::DX12DebugMessenger{ DX12InfoToken{ true }, callback, user_data @@ -21,8 +21,9 @@ VKAPI_ATTR VkBool32 VKAPI_CALL wis::ImplVKDebugExtension::DebugCallbackThunk( const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) noexcept { // Ignore this validation error, until it is fixed in the Vulkan SDK - if (pCallbackData->pMessageIdName && std::string_view(pCallbackData->pMessageIdName) == "VUID-vkCmdSetDescriptorBufferOffsetsEXT-pOffsets-08063") + if (pCallbackData->pMessageIdName && std::string_view(pCallbackData->pMessageIdName) == "VUID-vkCmdSetDescriptorBufferOffsetsEXT-pOffsets-08063") { return false; + } auto& [callback, user_data] = *reinterpret_cast*>(pUserData); @@ -35,12 +36,17 @@ VKAPI_ATTR VkBool32 VKAPI_CALL wis::ImplVKDebugExtension::DebugCallbackThunk( return false; } -wis::ResultValue -wis::ImplVKDebugExtension::CreateDebugMessenger(wis::DebugCallback callback, void* user_data) const noexcept +wis::VKDebugMessenger +wis::ImplVKDebugExtension::CreateDebugMessenger(wis::Result& result, wis::DebugCallback callback, void* user_data) const noexcept { - auto debug_callback = wis::detail::make_unique(callback, user_data); - if (!debug_callback) - return wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + VKDebugMessenger out_messenger; + auto& internal = out_messenger.GetMutableInternal(); + + internal.data = wis::detail::make_unique(callback, user_data); + if (!internal.data) { + result = wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + return out_messenger; + } VkDebugUtilsMessengerCreateInfoEXT create_info{ .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, @@ -51,16 +57,17 @@ wis::ImplVKDebugExtension::CreateDebugMessenger(wis::DebugCallback callback, voi VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, .pfnUserCallback = DebugCallbackThunk, - .pUserData = debug_callback.get() + .pUserData = internal.data.get() }; - - VkDebugUtilsMessengerEXT messenger; auto vr = vkCreateDebugUtilsMessengerEXT(instance.get(), &create_info, nullptr, - &messenger); - if (!wis::succeeded(vr)) - return wis::make_result(vr); - - return wis::VKDebugMessenger{ instance, messenger, std::move(debug_callback), vkDestroyDebugUtilsMessengerEXT }; + &internal.messenger); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return out_messenger; + } + internal.instance = instance; + internal.vkDestroyDebugUtilsMessengerEXT = vkDestroyDebugUtilsMessengerEXT; + return out_messenger; } #endif // WISDOM_VULKAN #endif // WISDOM_DEBUG_CPP diff --git a/wisdom/extensions/debug_info/wisdom/wisdom_debug.h b/wisdom/extensions/debug_info/wisdom/wisdom_debug.hpp similarity index 73% rename from wisdom/extensions/debug_info/wisdom/wisdom_debug.h rename to wisdom/extensions/debug_info/wisdom/wisdom_debug.hpp index 559d75d0..727011a5 100644 --- a/wisdom/extensions/debug_info/wisdom/wisdom_debug.h +++ b/wisdom/extensions/debug_info/wisdom/wisdom_debug.hpp @@ -24,11 +24,13 @@ class ImplDX12DebugExtension : public QueryInternalExtension debugController; if (wis::succeeded( - D3D12GetDebugInterface(__uuidof(*debugController), debugController.put_void()))) + D3D12GetDebugInterface(__uuidof(*debugController), debugController.put_void()))) { debugController->EnableDebugLayer(); + } - if (!debugController) + if (!debugController) { return wis::make_result(E_NOTIMPL); + } // if (auto dc = debugController.as()) // dc->SetEnableGPUBasedValidation(true); @@ -37,17 +39,28 @@ class ImplDX12DebugExtension : public QueryInternalExtension - CreateDebugMessenger(wis::DebugCallback callback, void* user_data) const noexcept; + [[nodiscard]] WIS_INLINE DX12DebugMessenger + CreateDebugMessenger(wis::Result& result, wis::DebugCallback callback, void* user_data) const noexcept; }; #pragma region DX12DebugExtension + class DX12DebugExtension : public wis::ImplDX12DebugExtension { public: using wis::ImplDX12DebugExtension::ImplDX12DebugExtension; public: + /** + * @brief Creates a debug messenger for the factory. + * @param callback The callback that will receive the debug messages. + * @param user_data The user data that will be passed to the callback. + * @return wis::DX12DebugMessenger on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12DebugMessenger CreateDebugMessenger(wis::Result& result, wis::DebugCallback callback, void* user_data) noexcept + { + return wis::ImplDX12DebugExtension::CreateDebugMessenger(result, callback, user_data); + } /** * @brief Creates a debug messenger for the factory. * @param callback The callback that will receive the debug messages. @@ -56,7 +69,7 @@ class DX12DebugExtension : public wis::ImplDX12DebugExtension * */ [[nodiscard]] inline wis::ResultValue CreateDebugMessenger(wis::DebugCallback callback, void* user_data) noexcept { - return wis::ImplDX12DebugExtension::CreateDebugMessenger(callback, user_data); + return wis::ResultValue{ &wis::ImplDX12DebugExtension::CreateDebugMessenger, this, callback, user_data }; } }; #pragma endregion DX12DebugExtension @@ -113,17 +126,28 @@ class ImplVKDebugExtension : public QueryInternalExtension - CreateDebugMessenger(wis::DebugCallback callback, void* user_data) const noexcept; + [[nodiscard]] WIS_INLINE VKDebugMessenger + CreateDebugMessenger(wis::Result& result, wis::DebugCallback callback, void* user_data) const noexcept; }; #pragma region VKDebugExtension + class VKDebugExtension : public wis::ImplVKDebugExtension { public: using wis::ImplVKDebugExtension::ImplVKDebugExtension; public: + /** + * @brief Creates a debug messenger for the factory. + * @param callback The callback that will receive the debug messages. + * @param user_data The user data that will be passed to the callback. + * @return wis::VKDebugMessenger on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKDebugMessenger CreateDebugMessenger(wis::Result& result, wis::DebugCallback callback, void* user_data) noexcept + { + return wis::ImplVKDebugExtension::CreateDebugMessenger(result, callback, user_data); + } /** * @brief Creates a debug messenger for the factory. * @param callback The callback that will receive the debug messages. @@ -132,7 +156,7 @@ class VKDebugExtension : public wis::ImplVKDebugExtension * */ [[nodiscard]] inline wis::ResultValue CreateDebugMessenger(wis::DebugCallback callback, void* user_data) noexcept { - return wis::ImplVKDebugExtension::CreateDebugMessenger(callback, user_data); + return wis::ResultValue{ &wis::ImplVKDebugExtension::CreateDebugMessenger, this, callback, user_data }; } }; #pragma endregion VKDebugExtension diff --git a/wisdom/extensions/descriptor_buffer/CMakeLists.txt b/wisdom/extensions/descriptor_buffer/CMakeLists.txt index 26ec06a3..e4dc32d7 100644 --- a/wisdom/extensions/descriptor_buffer/CMakeLists.txt +++ b/wisdom/extensions/descriptor_buffer/CMakeLists.txt @@ -14,10 +14,10 @@ target_include_directories( if(WISDOM_BUILD_BINARIES) add_library( wisdom-descriptor-buffer STATIC - "wisdom/wisdom_descriptor_buffer.h" - "wisdom/vk_descriptor_buffer.h" + "wisdom/wisdom_descriptor_buffer.hpp" + "wisdom/vk_descriptor_buffer.hpp" "wisdom/impl/vk_descriptor_buffer.cpp" - "wisdom/dx12_descriptor_buffer.h" + "wisdom/dx12_descriptor_buffer.hpp" "wisdom/impl/dx12_descriptor_buffer.cpp" "wisdom/impl/impl.dx.cpp" "wisdom/impl/impl.vk.cpp") diff --git a/wisdom/extensions/descriptor_buffer/wisdom/dx12_descriptor_buffer.h b/wisdom/extensions/descriptor_buffer/wisdom/dx12_descriptor_buffer.hpp similarity index 100% rename from wisdom/extensions/descriptor_buffer/wisdom/dx12_descriptor_buffer.h rename to wisdom/extensions/descriptor_buffer/wisdom/dx12_descriptor_buffer.hpp diff --git a/wisdom/extensions/descriptor_buffer/wisdom/impl/dx12_descriptor_buffer.cpp b/wisdom/extensions/descriptor_buffer/wisdom/impl/dx12_descriptor_buffer.cpp index db226d0d..d439e377 100644 --- a/wisdom/extensions/descriptor_buffer/wisdom/impl/dx12_descriptor_buffer.cpp +++ b/wisdom/extensions/descriptor_buffer/wisdom/impl/dx12_descriptor_buffer.cpp @@ -2,7 +2,7 @@ #define WIS_DX12_DESCRIPTOR_BUFFER_CPP #if defined(WISDOM_DX12) -#include +#include void wis::ImplDX12DescriptorBuffer::WriteSampler(uint64_t aligned_table_offset, uint32_t index, wis::DX12SamplerView sampler) noexcept { diff --git a/wisdom/extensions/descriptor_buffer/wisdom/impl/impl.dx.cpp b/wisdom/extensions/descriptor_buffer/wisdom/impl/impl.dx.cpp index 34f2c701..18631abf 100644 --- a/wisdom/extensions/descriptor_buffer/wisdom/impl/impl.dx.cpp +++ b/wisdom/extensions/descriptor_buffer/wisdom/impl/impl.dx.cpp @@ -2,7 +2,7 @@ #define WISDOM_DESCRIPTOR_BUFFER_DX_CPP #if defined(WISDOM_DX12) -#include +#include #include namespace wis::detail { @@ -23,22 +23,28 @@ constexpr inline D3D12_ROOT_PARAMETER_TYPE to_dx_ext(wis::DescriptorType type) n } } // namespace wis::detail -wis::ResultValue -wis::ImplDX12DescriptorBufferExtension::CreateRootSignature(const PushConstant* root_constants, +wis::DX12RootSignature +wis::ImplDX12DescriptorBufferExtension::CreateRootSignature(wis::Result& result, const PushConstant* root_constants, uint32_t constants_size, const PushDescriptor* push_descriptors, uint32_t push_descriptors_size, const wis::DescriptorTable* tables, uint32_t tables_count) const noexcept { + DX12RootSignature out_signature; + auto& internal = out_signature.GetMutableInternal(); + if (constants_size > wis::max_push_constants) { - return wis::make_result(E_INVALIDARG); + result = wis::make_result(E_INVALIDARG); + return out_signature; } if (push_descriptors_size > wis::max_push_descriptors) { - return wis::make_result(E_INVALIDARG); + result = wis::make_result(E_INVALIDARG); + return out_signature; } if (tables_count + constants_size + push_descriptors_size > 64) { - return wis::make_result(E_INVALIDARG); + result = wis::make_result(E_INVALIDARG); + return out_signature; } D3D12_ROOT_PARAMETER1 root_params[64]{}; // max overall size of root parameters @@ -81,8 +87,10 @@ wis::ImplDX12DescriptorBufferExtension::CreateRootSignature(const PushConstant* } auto memory = wis::detail::make_unique_for_overwrite(memory_size); - if (!memory) - return wis::make_result(E_OUTOFMEMORY); + if (!memory) { + result = wis::make_result(E_OUTOFMEMORY); + return out_signature; + } uint32_t offset = 0; for (uint32_t i = constants_size; i < constants_size + tables_count; ++i) { @@ -119,24 +127,31 @@ wis::ImplDX12DescriptorBufferExtension::CreateRootSignature(const PushConstant* wis::com_ptr error; HRESULT hr = D3D12SerializeVersionedRootSignature(&desc, signature.put(), error.put()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_signature; + } - wis::com_ptr rsig; hr = device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), - __uuidof(*rsig), rsig.put_void()); - - if (!wis::succeeded(hr)) - return wis::make_result(hr); - - return DX12RootSignature{ std::move(rsig), stage_map, constants_size, push_descriptors_size }; + __uuidof(*internal.root), internal.root.put_void()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_signature; + } + internal.push_constant_count = constants_size; + internal.push_descriptor_count = push_descriptors_size; + internal.stage_map = stage_map; + return out_signature; } -wis::ResultValue -wis::ImplDX12DescriptorBufferExtension::CreateDescriptorBuffer(wis::DescriptorHeapType heap_type, +wis::DX12DescriptorBuffer +wis::ImplDX12DescriptorBufferExtension::CreateDescriptorBuffer(wis::Result& result, wis::DescriptorHeapType heap_type, wis::DescriptorMemory memory_type, uint64_t memory_bytes) const noexcept { + DX12DescriptorBuffer out_buffer; + auto& internal = out_buffer.GetMutableInternal(); + auto xheap_type = convert_dx(heap_type); auto inc_size = device->GetDescriptorHandleIncrementSize(xheap_type); auto aligned_size = wis::detail::aligned_size(memory_bytes, uint64_t(inc_size)); @@ -146,12 +161,17 @@ wis::ImplDX12DescriptorBufferExtension::CreateDescriptorBuffer(wis::DescriptorHe .Flags = convert_dx(memory_type), .NodeMask = 0, }; - wis::com_ptr heap; - auto hr = device->CreateDescriptorHeap(&desc, heap.iid(), heap.put_void()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); - return DX12DescriptorBuffer{ std::move(heap), device->GetDescriptorHandleIncrementSize(desc.Type) }; + auto hr = device->CreateDescriptorHeap(&desc, internal.heap.iid(), internal.heap.put_void()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_buffer; + } + internal.heap_increment = device->GetDescriptorHandleIncrementSize(desc.Type); + internal.heap_start = CD3DX12_CPU_DESCRIPTOR_HANDLE(internal.heap->GetCPUDescriptorHandleForHeapStart()); + internal.heap_gpu_start = CD3DX12_GPU_DESCRIPTOR_HANDLE(internal.heap->GetGPUDescriptorHandleForHeapStart()); + internal.heap->GetDevice(internal.device.iid(), internal.device.put_void()); + return out_buffer; } void wis::ImplDX12DescriptorBufferExtension::SetDescriptorBuffers(wis::DX12CommandListView cmd_list, diff --git a/wisdom/extensions/descriptor_buffer/wisdom/impl/impl.vk.cpp b/wisdom/extensions/descriptor_buffer/wisdom/impl/impl.vk.cpp index ab7ed067..809ff383 100644 --- a/wisdom/extensions/descriptor_buffer/wisdom/impl/impl.vk.cpp +++ b/wisdom/extensions/descriptor_buffer/wisdom/impl/impl.vk.cpp @@ -1,6 +1,6 @@ #ifndef WISDOM_DESCRIPTOR_BUFFER_VK_CPP #define WISDOM_DESCRIPTOR_BUFFER_VK_CPP -#include +#include #if defined(WISDOM_VULKAN) bool wis::ImplVKDescriptorBufferExtension::GetExtensionInfo(const std::unordered_map>& available_extensions, @@ -12,8 +12,9 @@ bool wis::ImplVKDescriptorBufferExtension::GetExtensionInfo(const std::unordered ext_name_set.insert(VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME); structure_map[VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT] = sizeof(VkPhysicalDeviceDescriptorBufferFeaturesEXT); property_map[VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT] = sizeof(VkPhysicalDeviceDescriptorBufferPropertiesEXT); - } else + } else { return false; + } if (available_extensions.contains(VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME)) { ext_name_set.insert(VK_EXT_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME); @@ -21,8 +22,9 @@ bool wis::ImplVKDescriptorBufferExtension::GetExtensionInfo(const std::unordered } else if (available_extensions.contains(VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME)) { ext_name_set.insert(VK_VALVE_MUTABLE_DESCRIPTOR_TYPE_EXTENSION_NAME); structure_map[VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE] = sizeof(VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE); - } else + } else { return false; + } return true; } @@ -64,30 +66,36 @@ wis::ImplVKDescriptorBufferExtension::Init(const wis::VKDevice& instance, return wis::success; } -wis::ResultValue -wis::ImplVKDescriptorBufferExtension::CreateRootSignature(const PushConstant* constants, +wis::VKRootSignature +wis::ImplVKDescriptorBufferExtension::CreateRootSignature(wis::Result& result, const PushConstant* constants, uint32_t constants_size, const PushDescriptor* push_descriptors, uint32_t push_descriptors_size, const wis::DescriptorTable* tables, uint32_t tables_count) const noexcept { + VKRootSignature out_signature; + auto& internal = out_signature.GetMutableInternal(); if (constants_size > wis::max_push_constants) { - return wis::make_result(VkResult::VK_ERROR_UNKNOWN); + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_signature; } if (push_descriptors_size > wis::max_push_descriptors) { - return wis::make_result(VkResult::VK_ERROR_UNKNOWN); + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_signature; } - std::unique_ptr vk_dsl; + uint32_t table_offset = push_descriptors_size > 0; if (tables_count > 0 || push_descriptors_size > 0) { - if (vk_dsl = wis::detail::make_unique_for_overwrite(tables_count + 1); !vk_dsl) - return wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + if (internal.vk_dsls = wis::detail::make_unique_for_overwrite(tables_count + table_offset); !internal.vk_dsls) { + result = wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + return out_signature; + } } // Create push descriptor set layout - { + if (table_offset) { uint32_t push_binding_count = constants_size; VkDescriptorSetLayoutBinding push_bindings[wis::max_push_descriptors]{}; for (uint32_t i = 0; i < push_binding_count; i++) { @@ -101,13 +109,15 @@ wis::ImplVKDescriptorBufferExtension::CreateRootSignature(const PushConstant* co VkDescriptorSetLayoutCreateInfo push_desc_info{ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, .pNext = nullptr, - .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, + .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR | VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT, .bindingCount = push_binding_count, .pBindings = push_bindings, }; - auto res = device.table().vkCreateDescriptorSetLayout(device.get(), &push_desc_info, nullptr, &vk_dsl[0]); - if (!succeeded(res)) - return wis::make_result(res); + auto res = device.table().vkCreateDescriptorSetLayout(device.get(), &push_desc_info, nullptr, &internal.vk_dsls[0]); + if (!succeeded(res)) { + result = wis::make_result(res); + return out_signature; + } } VkPushConstantRange push_constants[wis::max_push_constants]{}; // max push constants @@ -119,44 +129,46 @@ wis::ImplVKDescriptorBufferExtension::CreateRootSignature(const PushConstant* co c.size = r.size_bytes; } - for (size_t i = 1; i < tables_count + 1; i++) { - auto [res, h] = CreateDescriptorSetLayout(&tables[i]); - if (res.status != wis::Status::Ok) { - for (size_t j = 0; j < i; j++) - device.table().vkDestroyDescriptorSetLayout(device.get(), vk_dsl[j], nullptr); + for (size_t i = 0; i < tables_count; i++) { + auto h = CreateDescriptorSetLayout(result, &tables[i]); + if (result.status != wis::Status::Ok) { + for (size_t j = 0; j < i + table_offset; j++) { + device.table().vkDestroyDescriptorSetLayout(device.get(), internal.vk_dsls[j], nullptr); + } - return res; + return out_signature; } - vk_dsl[i] = h; + internal.vk_dsls[i + table_offset] = h; } VkPipelineLayoutCreateInfo pipeline_layout_info{ .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .pNext = nullptr, .flags = 0, - .setLayoutCount = tables_count + 1, // push descriptor set layout - .pSetLayouts = vk_dsl.get(), + .setLayoutCount = tables_count + table_offset, // push descriptor set layout + .pSetLayouts = internal.vk_dsls.get(), .pushConstantRangeCount = constants_size, .pPushConstantRanges = push_constants, }; - VkPipelineLayout layout; - auto vr = device.table().vkCreatePipelineLayout(device.get(), &pipeline_layout_info, nullptr, &layout); - + auto vr = device.table().vkCreatePipelineLayout(device.get(), &pipeline_layout_info, nullptr, internal.root.put(device, device.table().vkDestroyPipelineLayout)); if (!succeeded(vr)) { - for (uint32_t i = 0; i < tables_count; i++) - device.table().vkDestroyDescriptorSetLayout(device.get(), vk_dsl[i], nullptr); - - return wis::make_result(vr); + for (uint32_t i = 0; i < tables_count; i++) { + device.table().vkDestroyDescriptorSetLayout(device.get(), internal.vk_dsls[i], nullptr); + } + result = wis::make_result(vr); + return out_signature; } - - return VKRootSignature{ wis::managed_handle_ex{ layout, device, device.table().vkDestroyPipelineLayout }, std::move(vk_dsl), tables_count }; + internal.dsl_count = tables_count + table_offset; // number of descriptor set layouts to destroy + return out_signature; } -wis::ResultValue -wis::ImplVKDescriptorBufferExtension::CreateDescriptorBuffer(wis::DescriptorHeapType heap_type, +wis::VKDescriptorBuffer +wis::ImplVKDescriptorBufferExtension::CreateDescriptorBuffer(wis::Result& result, wis::DescriptorHeapType heap_type, wis::DescriptorMemory memory_type, uint64_t memory_bytes) const noexcept { + VKDescriptorBuffer out_buffer; + auto& internal = out_buffer.GetMutableInternal(); uint32_t descriptor_size = heap_type == wis::DescriptorHeapType::Descriptor ? descriptor_buffer_props.mutable_descriptor_size @@ -184,23 +196,28 @@ wis::ImplVKDescriptorBufferExtension::CreateDescriptorBuffer(wis::DescriptorHeap .requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, .preferredFlags = 0, }; - - VkBuffer buffer; - VmaAllocation allocation; - - auto result = vmaCreateBuffer(allocator.get(), &info, &alloc_info, &buffer, &allocation, nullptr); - if (!succeeded(result)) - return wis::make_result(result); - - return wis::VKDescriptorBuffer{ - wis::Internal{ - allocator, - buffer, - allocation, - heap_type, - descriptor_buffer_props, - ftable } + auto vr = vmaCreateBuffer(allocator.get(), &info, &alloc_info, &internal.buffer, &internal.allocation, nullptr); + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_buffer; + } + internal.allocator = allocator; + internal.type = heap_type; + internal.properties = descriptor_buffer_props; + internal.vkGetDescriptorEXT = ftable.vkGetDescriptorEXT; + + auto& device = this->allocator.header(); + VkBufferDeviceAddressInfo address_info{ + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + .buffer = internal.buffer }; + internal.address = device.table().vkGetBufferDeviceAddress(device.get(), &address_info); + vmaMapMemory(this->allocator.get(), internal.allocation, reinterpret_cast(&internal.data)); + internal.descriptor_size = internal.type == wis::DescriptorHeapType::Descriptor + ? descriptor_buffer_props.mutable_descriptor_size + : descriptor_buffer_props.sampler_size; + + return out_buffer; } void wis::ImplVKDescriptorBufferExtension::SetDescriptorBuffers(wis::VKCommandListView cmd_list, wis::VKDescriptorBufferView resource_desc_buffer, @@ -244,8 +261,8 @@ void wis::ImplVKDescriptorBufferExtension::SetDescriptorTableOffset(wis::VKComma // Auxiliary functions -wis::ResultValue -wis::ImplVKDescriptorBufferExtension::VKCreateDescriptorSetDescriptorLayout(const wis::DescriptorTable* table) const noexcept +VkDescriptorSetLayout +wis::ImplVKDescriptorBufferExtension::VKCreateDescriptorSetDescriptorLayout(wis::Result& result, const wis::DescriptorTable* table) const noexcept { constexpr static VkDescriptorType cbvSrvUavTypes[] = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, @@ -266,8 +283,9 @@ wis::ImplVKDescriptorBufferExtension::VKCreateDescriptorSetDescriptorLayout(cons wis::detail::limited_allocator binding_flags{ table->entry_count, true }; wis::detail::limited_allocator bindings_mutable{ table->entry_count }; - for (size_t i = 0; i < table->entry_count; i++) + for (size_t i = 0; i < table->entry_count; i++) { bindings_mutable.data()[i] = a; + } VkDescriptorSetLayoutBindingFlagsCreateInfoEXT binding_flags_info{ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT, @@ -306,16 +324,15 @@ wis::ImplVKDescriptorBufferExtension::VKCreateDescriptorSetDescriptorLayout(cons }; VkDescriptorSetLayout layout; - auto result = device.table().vkCreateDescriptorSetLayout(device.get(), &desc, nullptr, &layout); - - if (!succeeded(result)) - return wis::make_result(result); - + auto vr = device.table().vkCreateDescriptorSetLayout(device.get(), &desc, nullptr, &layout); + if (!succeeded(vr)) { + result = wis::make_result(vr); + } return layout; } -wis::ResultValue -wis::ImplVKDescriptorBufferExtension::VKCreateDescriptorSetSamplerLayout(const wis::DescriptorTable* table) const noexcept +VkDescriptorSetLayout +wis::ImplVKDescriptorBufferExtension::VKCreateDescriptorSetSamplerLayout(wis::Result& result, const wis::DescriptorTable* table) const noexcept { wis::detail::limited_allocator bindings{ table->entry_count, true }; @@ -339,11 +356,10 @@ wis::ImplVKDescriptorBufferExtension::VKCreateDescriptorSetSamplerLayout(const w }; VkDescriptorSetLayout layout; - auto result = device.table().vkCreateDescriptorSetLayout(device.get(), &desc, nullptr, &layout); - - if (!succeeded(result)) - return wis::make_result(result); - + auto vr = device.table().vkCreateDescriptorSetLayout(device.get(), &desc, nullptr, &layout); + if (!succeeded(vr)) { + result = wis::make_result(vr); + } return layout; } diff --git a/wisdom/extensions/descriptor_buffer/wisdom/impl/vk_descriptor_buffer.cpp b/wisdom/extensions/descriptor_buffer/wisdom/impl/vk_descriptor_buffer.cpp index b1669dab..0544ade2 100644 --- a/wisdom/extensions/descriptor_buffer/wisdom/impl/vk_descriptor_buffer.cpp +++ b/wisdom/extensions/descriptor_buffer/wisdom/impl/vk_descriptor_buffer.cpp @@ -2,7 +2,7 @@ #define WIS_VK_DESCRIPTOR_BUFFER_CPP #if defined(WISDOM_VULKAN) -#include +#include void wis::ImplVKDescriptorBuffer::WriteSampler(uint64_t aligned_table_offset, uint32_t index, wis::VKSamplerView sampler) noexcept { diff --git a/wisdom/extensions/descriptor_buffer/wisdom/vk_descriptor_buffer.h b/wisdom/extensions/descriptor_buffer/wisdom/vk_descriptor_buffer.hpp similarity index 100% rename from wisdom/extensions/descriptor_buffer/wisdom/vk_descriptor_buffer.h rename to wisdom/extensions/descriptor_buffer/wisdom/vk_descriptor_buffer.hpp diff --git a/wisdom/extensions/descriptor_buffer/wisdom/wisdom_descriptor_buffer.h b/wisdom/extensions/descriptor_buffer/wisdom/wisdom_descriptor_buffer.hpp similarity index 73% rename from wisdom/extensions/descriptor_buffer/wisdom/wisdom_descriptor_buffer.h rename to wisdom/extensions/descriptor_buffer/wisdom/wisdom_descriptor_buffer.hpp index 4d9dfe8b..a6f77474 100644 --- a/wisdom/extensions/descriptor_buffer/wisdom/wisdom_descriptor_buffer.h +++ b/wisdom/extensions/descriptor_buffer/wisdom/wisdom_descriptor_buffer.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include namespace wis { @@ -29,8 +29,8 @@ class ImplDX12DescriptorBufferExtension : public QueryInternalExtension - CreateRootSignature(const PushConstant* root_constants = nullptr, + [[nodiscard]] WIS_INLINE wis::DX12RootSignature + CreateRootSignature(wis::Result& result, const PushConstant* root_constants = nullptr, uint32_t constants_size = 0, const PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_size = 0, @@ -48,8 +48,8 @@ class ImplDX12DescriptorBufferExtension : public QueryInternalExtensionGetDescriptorHandleIncrementSize(wis::convert_dx(heap)); } - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateDescriptorBuffer(wis::DescriptorHeapType heap_type, wis::DescriptorMemory memory_type, uint64_t memory_bytes) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12DescriptorBuffer + CreateDescriptorBuffer(wis::Result& result, wis::DescriptorHeapType heap_type, wis::DescriptorMemory memory_type, uint64_t memory_bytes) const noexcept; public: // Command List WIS_INLINE void SetDescriptorBuffers(wis::DX12CommandListView cmd_list, @@ -64,12 +64,27 @@ class ImplDX12DescriptorBufferExtension : public QueryInternalExtension CreateRootSignature(const wis::PushConstant* root_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* root_descriptors = nullptr, uint32_t descriptors_count = 0, const wis::DescriptorTable* tables = nullptr, uint32_t tables_count = 0) const noexcept { - return wis::ImplDX12DescriptorBufferExtension::CreateRootSignature(root_constants, constants_count, root_descriptors, descriptors_count, tables, tables_count); + return wis::ResultValue{ &wis::ImplDX12DescriptorBufferExtension::CreateRootSignature, this, root_constants, constants_count, root_descriptors, descriptors_count, tables, tables_count }; + } + /** + * @brief Creates a descriptor buffer object. + * @param type The type of the descriptor buffer to create. + * @param memory Memory location of the buffer (CPU or GPU). + * @param memory_bytes The size of the descriptor buffer in bytes. + * @return wis::DX12DescriptorBuffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12DescriptorBuffer CreateDescriptorBuffer(wis::Result& result, wis::DescriptorHeapType type, wis::DescriptorMemory memory, uint64_t memory_bytes) const noexcept + { + return wis::ImplDX12DescriptorBufferExtension::CreateDescriptorBuffer(result, type, memory, memory_bytes); } /** * @brief Creates a descriptor buffer object. @@ -93,7 +119,7 @@ class DX12DescriptorBufferExtension : public wis::ImplDX12DescriptorBufferExtens * */ [[nodiscard]] inline wis::ResultValue CreateDescriptorBuffer(wis::DescriptorHeapType type, wis::DescriptorMemory memory, uint64_t memory_bytes) const noexcept { - return wis::ImplDX12DescriptorBufferExtension::CreateDescriptorBuffer(type, memory, memory_bytes); + return wis::ResultValue{ &wis::ImplDX12DescriptorBufferExtension::CreateDescriptorBuffer, this, type, memory, memory_bytes }; } /** * @brief Returns the alignment of the descriptor table in bytes. @@ -147,7 +173,7 @@ class DX12DescriptorBufferExtension : public wis::ImplDX12DescriptorBufferExtens #include #include #include -#include +#include namespace wis { class VKDescriptorBufferExtension; @@ -181,8 +207,8 @@ class ImplVKDescriptorBufferExtension : public QueryInternalExtension - CreateRootSignature(const PushConstant* constants = nullptr, + [[nodiscard]] WIS_INLINE wis::VKRootSignature + CreateRootSignature(wis::Result& result, const PushConstant* constants = nullptr, uint32_t constants_size = 0, const PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_size = 0, @@ -204,8 +230,8 @@ class ImplVKDescriptorBufferExtension : public QueryInternalExtension - CreateDescriptorBuffer(wis::DescriptorHeapType heap_type, + [[nodiscard]] WIS_INLINE VKDescriptorBuffer + CreateDescriptorBuffer(wis::Result& result, wis::DescriptorHeapType heap_type, wis::DescriptorMemory memory_type, uint64_t memory_bytes) const noexcept; @@ -221,24 +247,39 @@ class ImplVKDescriptorBufferExtension : public QueryInternalExtension - CreateDescriptorSetLayout(const wis::DescriptorTable* table) const noexcept + [[nodiscard]] VkDescriptorSetLayout + CreateDescriptorSetLayout(wis::Result& result, const wis::DescriptorTable* table) const noexcept { return table->type == wis::DescriptorHeapType::Descriptor - ? VKCreateDescriptorSetDescriptorLayout(table) - : VKCreateDescriptorSetSamplerLayout(table); + ? VKCreateDescriptorSetDescriptorLayout(result, table) + : VKCreateDescriptorSetSamplerLayout(result, table); } - WIS_INLINE wis::ResultValue VKCreateDescriptorSetDescriptorLayout(const wis::DescriptorTable* table) const noexcept; - WIS_INLINE wis::ResultValue VKCreateDescriptorSetSamplerLayout(const wis::DescriptorTable* table) const noexcept; + WIS_INLINE VkDescriptorSetLayout VKCreateDescriptorSetDescriptorLayout(wis::Result& result, const wis::DescriptorTable* table) const noexcept; + WIS_INLINE VkDescriptorSetLayout VKCreateDescriptorSetSamplerLayout(wis::Result& result, const wis::DescriptorTable* table) const noexcept; }; #pragma region VKDescriptorBufferExtension + class VKDescriptorBufferExtension : public wis::ImplVKDescriptorBufferExtension { public: using wis::ImplVKDescriptorBufferExtension::ImplVKDescriptorBufferExtension; public: + /** + * @brief Creates a root signature object. + * @param root_constants The root constants to create the root signature with. + * @param constants_count The number of root constants. Max is 5. + * @param root_descriptors The root descriptors to create the root signature with. + * @param descriptors_count The number of root descriptors. Max is 8. + * @param tables The descriptor tables to create the root signature with. + * @param tables_count The number of descriptor tables. + * @return wis::VKRootSignature on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKRootSignature CreateRootSignature(wis::Result& result, const wis::PushConstant* root_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* root_descriptors = nullptr, uint32_t descriptors_count = 0, const wis::DescriptorTable* tables = nullptr, uint32_t tables_count = 0) const noexcept + { + return wis::ImplVKDescriptorBufferExtension::CreateRootSignature(result, root_constants, constants_count, root_descriptors, descriptors_count, tables, tables_count); + } /** * @brief Creates a root signature object. * @param root_constants The root constants to create the root signature with. @@ -251,7 +292,18 @@ class VKDescriptorBufferExtension : public wis::ImplVKDescriptorBufferExtension * */ [[nodiscard]] inline wis::ResultValue CreateRootSignature(const wis::PushConstant* root_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* root_descriptors = nullptr, uint32_t descriptors_count = 0, const wis::DescriptorTable* tables = nullptr, uint32_t tables_count = 0) const noexcept { - return wis::ImplVKDescriptorBufferExtension::CreateRootSignature(root_constants, constants_count, root_descriptors, descriptors_count, tables, tables_count); + return wis::ResultValue{ &wis::ImplVKDescriptorBufferExtension::CreateRootSignature, this, root_constants, constants_count, root_descriptors, descriptors_count, tables, tables_count }; + } + /** + * @brief Creates a descriptor buffer object. + * @param type The type of the descriptor buffer to create. + * @param memory Memory location of the buffer (CPU or GPU). + * @param memory_bytes The size of the descriptor buffer in bytes. + * @return wis::VKDescriptorBuffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKDescriptorBuffer CreateDescriptorBuffer(wis::Result& result, wis::DescriptorHeapType type, wis::DescriptorMemory memory, uint64_t memory_bytes) const noexcept + { + return wis::ImplVKDescriptorBufferExtension::CreateDescriptorBuffer(result, type, memory, memory_bytes); } /** * @brief Creates a descriptor buffer object. @@ -262,7 +314,7 @@ class VKDescriptorBufferExtension : public wis::ImplVKDescriptorBufferExtension * */ [[nodiscard]] inline wis::ResultValue CreateDescriptorBuffer(wis::DescriptorHeapType type, wis::DescriptorMemory memory, uint64_t memory_bytes) const noexcept { - return wis::ImplVKDescriptorBufferExtension::CreateDescriptorBuffer(type, memory, memory_bytes); + return wis::ResultValue{ &wis::ImplVKDescriptorBufferExtension::CreateDescriptorBuffer, this, type, memory, memory_bytes }; } /** * @brief Returns the alignment of the descriptor table in bytes. diff --git a/wisdom/extensions/extended_allocation/CMakeLists.txt b/wisdom/extensions/extended_allocation/CMakeLists.txt index ebc776b1..a6ef28ac 100644 --- a/wisdom/extensions/extended_allocation/CMakeLists.txt +++ b/wisdom/extensions/extended_allocation/CMakeLists.txt @@ -15,7 +15,7 @@ target_include_directories( if(WISDOM_BUILD_BINARIES) add_library( wisdom-extended-allocation STATIC - "wisdom/wisdom_extended_allocation.h" "wisdom/impl/impl.dx.cpp" + "wisdom/wisdom_extended_allocation.hpp" "wisdom/impl/impl.dx.cpp" "wisdom/impl/impl.vk.cpp") add_library(wis::extended-allocation ALIAS wisdom-extended-allocation) target_link_libraries(wisdom-extended-allocation PUBLIC wis::wisdom) diff --git a/wisdom/extensions/extended_allocation/wisdom/impl/impl.dx.cpp b/wisdom/extensions/extended_allocation/wisdom/impl/impl.dx.cpp index f99ac18e..456c3ef0 100644 --- a/wisdom/extensions/extended_allocation/wisdom/impl/impl.dx.cpp +++ b/wisdom/extensions/extended_allocation/wisdom/impl/impl.dx.cpp @@ -1,19 +1,25 @@ #ifndef WISDOM_EXTENDED_ALLOCATION_DX_CPP #define WISDOM_EXTENDED_ALLOCATION_DX_CPP -#include +#include #if defined(WISDOM_DX12) #include #include -wis::ResultValue -wis::DX12ExtendedAllocation::CreateGPUUploadTexture(const wis::DX12ResourceAllocator& allocator, - wis::TextureDesc desc, - wis::TextureState initial_state, - wis::MemoryFlags flags) const noexcept +wis::DX12Texture +wis::ImplDX12ExtendedAllocation::CreateGPUUploadTexture(wis::Result& result, const wis::DX12ResourceAllocator& allocator, + wis::TextureDesc desc, + wis::TextureState initial_state, + wis::MemoryFlags flags) const noexcept { - if (!supports_gpu_upload) - return wis::make_result(E_INVALIDARG); + DX12Texture out_texture; + auto& internal = out_texture.GetMutableInternal(); + auto& mem_internal = internal.memory.GetMutableInternal(); + + if (!supports_gpu_upload) { + result = wis::make_result(E_INVALIDARG); + return out_texture; + } D3D12_RESOURCE_DESC1 tex_desc; DX12ResourceAllocator::DX12FillTextureDesc(desc, tex_desc); @@ -23,27 +29,23 @@ wis::DX12ExtendedAllocation::CreateGPUUploadTexture(const wis::DX12ResourceAlloc .HeapType = convert_dx(wis::MemoryType::GPUUpload), .ExtraHeapFlags = D3D12_HEAP_FLAG_DENY_BUFFERS }; + HRESULT hr = allocator.GetInternal().allocator->CreateResource3(&all_desc, &tex_desc, + convert_dx(initial_state), nullptr, 0, nullptr, + mem_internal.allocation.put(), __uuidof(*internal.resource), internal.resource.put_void()); - wis::com_ptr rc; - wis::com_ptr al; - - auto hallocator = allocator.GetInternal().allocator; - - HRESULT hr = hallocator->CreateResource3(&all_desc, &tex_desc, - convert_dx(initial_state), nullptr, 0, nullptr, - al.put(), __uuidof(*rc), rc.put_void()); - - if (!wis::succeeded(hr)) - return wis::make_result(hr); - - return DX12Buffer{ std::move(rc), std::move(al), std::move(hallocator) }; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_texture; + } + mem_internal.allocator = allocator.GetInternal().allocator; + return out_texture; } wis::Result -wis::DX12ExtendedAllocation::WriteMemoryToSubresourceDirect(const void* host_data, - wis::DX12TextureView dst_texture, - wis::TextureState initial_state, - wis::TextureRegion region) const noexcept +wis::ImplDX12ExtendedAllocation::WriteMemoryToSubresourceDirect(const void* host_data, + wis::DX12TextureView dst_texture, + wis::TextureState initial_state, + wis::TextureRegion region) const noexcept { auto resource = std::get<0>(dst_texture); auto texture_desc = resource->GetDesc(); @@ -52,12 +54,14 @@ wis::DX12ExtendedAllocation::WriteMemoryToSubresourceDirect(const void* host_dat UINT row_pitch = 0; UINT slice_pitch = 0; auto hr = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::CalculateMinimumRowMajorRowPitch(convert_dx(region.format), region.size.width, row_pitch); - if (!wis::succeeded(hr)) + if (!wis::succeeded(hr)) { return wis::make_result(hr); + } hr = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::CalculateMinimumRowMajorSlicePitch(convert_dx(region.format), row_pitch, region.size.height, slice_pitch); - if (!wis::succeeded(hr)) + if (!wis::succeeded(hr)) { return wis::make_result(hr); + } D3D12_BOX box{ .left = region.offset.width, @@ -68,8 +72,9 @@ wis::DX12ExtendedAllocation::WriteMemoryToSubresourceDirect(const void* host_dat .back = region.offset.depth_or_layers + region.size.depth_or_layers, }; hr = resource->WriteToSubresource(dest_subresource, &box, host_data, row_pitch, slice_pitch); - if (!wis::succeeded(hr)) + if (!wis::succeeded(hr)) { return wis::make_result(hr); + } return wis::success; } #endif // WISDOM_DX12 diff --git a/wisdom/extensions/extended_allocation/wisdom/impl/impl.vk.cpp b/wisdom/extensions/extended_allocation/wisdom/impl/impl.vk.cpp index f196aac3..9525089c 100644 --- a/wisdom/extensions/extended_allocation/wisdom/impl/impl.vk.cpp +++ b/wisdom/extensions/extended_allocation/wisdom/impl/impl.vk.cpp @@ -1,12 +1,12 @@ #ifndef WISDOM_EXTENDED_ALLOCATION_VK_CPP #define WISDOM_EXTENDED_ALLOCATION_VK_CPP -#include +#include #if defined(WISDOM_VULKAN) -bool wis::VKExtendedAllocation::GetExtensionInfo(const std::unordered_map>& available_extensions, - std::unordered_set& ext_name_set, - std::unordered_map& structure_map, - std::unordered_map& property_map) noexcept +bool wis::ImplVKExtendedAllocation::GetExtensionInfo(const std::unordered_map>& available_extensions, + std::unordered_set& ext_name_set, + std::unordered_map& structure_map, + std::unordered_map& property_map) noexcept { if (available_extensions.contains(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME)) { ext_name_set.emplace(VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME); @@ -21,9 +21,9 @@ bool wis::VKExtendedAllocation::GetExtensionInfo(const std::unordered_map& structure_map, - const std::unordered_map& property_map) noexcept +wis::ImplVKExtendedAllocation::Init(const wis::VKDevice& instance, + const std::unordered_map& structure_map, + const std::unordered_map& property_map) noexcept { if (!structure_map.contains(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT)) { return {}; @@ -46,47 +46,60 @@ wis::VKExtendedAllocation::Init(const wis::VKDevice& instance, return {}; } -wis::ResultValue -wis::VKExtendedAllocation::CreateGPUUploadTexture(const wis::VKResourceAllocator& allocator, - wis::TextureDesc desc, - wis::TextureState initial_state, - wis::MemoryFlags flags) const noexcept +wis::VKTexture +wis::ImplVKExtendedAllocation::CreateGPUUploadTexture(wis::Result& result, const wis::VKResourceAllocator& allocator, + wis::TextureDesc desc, + wis::TextureState initial_state, + wis::MemoryFlags flags) const noexcept { - if (!vkCopyMemoryToImageEXT) - return wis::make_result(VK_ERROR_UNKNOWN); - - VkImageCreateInfo info; - VKResourceAllocator::VKFillImageDesc(desc, info); - auto [res, texture] = allocator.CreateTexture(desc, wis::MemoryType::GPUUpload, flags); - - // Transition image layout to general for host copy layouts - auto& tex_i = texture.GetInternal(); - VkHostImageLayoutTransitionInfoEXT transition{ - .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT, - .pNext = nullptr, - .image = texture.GetInternal().buffer, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = convert_vk(initial_state), - .subresourceRange = { - .aspectMask = wis::aspect_flags(tex_i.format), - .baseMipLevel = 0, - .levelCount = desc.mip_levels, - .baseArrayLayer = 0, - .layerCount = info.arrayLayers, - }, + auto synth_1 = [this](wis::Result& result, const wis::VKResourceAllocator& allocator, + wis::TextureDesc desc, + wis::TextureState initial_state, + wis::MemoryFlags flags) { + VkImageCreateInfo info; + VKResourceAllocator::VKFillImageDesc(desc, info); + wis::VKTexture texture = allocator.CreateTexture(result, desc, wis::MemoryType::GPUUpload, flags); + if (result.status != wis::Status::Ok) { + return texture; + } + + // Transition image layout to general for host copy layouts + auto& tex_i = texture.GetInternal(); + VkHostImageLayoutTransitionInfoEXT transition{ + .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT, + .pNext = nullptr, + .image = texture.GetInternal().buffer, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = convert_vk(initial_state), + .subresourceRange = { + .aspectMask = wis::aspect_flags(tex_i.format), + .baseMipLevel = 0, + .levelCount = desc.mip_levels, + .baseArrayLayer = 0, + .layerCount = info.arrayLayers, + }, + }; + + auto vr = vkTransitionImageLayoutEXT(device.get(), 1, &transition); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + } + return texture; }; - auto vr = vkTransitionImageLayoutEXT(device.get(), 1, &transition); - if (!wis::succeeded(vr)) - return wis::make_result(vr); - return std::move(texture); + if (!vkCopyMemoryToImageEXT) { + result = wis::make_result(VK_ERROR_UNKNOWN); + return {}; + } else { + return synth_1(result, allocator, desc, initial_state, flags); + } } wis::Result -wis::VKExtendedAllocation::WriteMemoryToSubresourceDirect(const void* host_data, - wis::VKTextureView dst_texture, - wis::TextureState initial_state, - wis::TextureRegion region) const noexcept +wis::ImplVKExtendedAllocation::WriteMemoryToSubresourceDirect(const void* host_data, + wis::VKTextureView dst_texture, + wis::TextureState initial_state, + wis::TextureRegion region) const noexcept { auto aspects = aspect_flags(std::get<1>(dst_texture)); @@ -117,12 +130,13 @@ wis::VKExtendedAllocation::WriteMemoryToSubresourceDirect(const void* host_data, }; auto vr = vkCopyMemoryToImageEXT(device.get(), ©_info); - if (!wis::succeeded(vr)) + if (!wis::succeeded(vr)) { return wis::make_result(vr); + } return wis::success; } -bool wis::VKExtendedAllocation::SupportedDirectGPUUpload(wis::DataFormat format) const noexcept +bool wis::ImplVKExtendedAllocation::SupportedDirectGPUUpload(wis::DataFormat format) const noexcept { VkHostImageCopyDevicePerformanceQueryEXT query{ .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT, diff --git a/wisdom/extensions/extended_allocation/wisdom/wisdom_extended_allocation.h b/wisdom/extensions/extended_allocation/wisdom/wisdom_extended_allocation.h deleted file mode 100644 index bb607469..00000000 --- a/wisdom/extensions/extended_allocation/wisdom/wisdom_extended_allocation.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef WISDOM_EXTENDED_ALLOCATION_H -#define WISDOM_EXTENDED_ALLOCATION_H -#if defined(WISDOM_DX12) -#include -#include -#include -#include - -namespace wis { -class DX12ExtendedAllocation; - -template<> -struct Internal { - bool supports_gpu_upload = false; -}; - -class DX12ExtendedAllocation : public QueryInternalExtension -{ -protected: - virtual wis::Result Init(const wis::DX12Device& instance) noexcept override - { - D3D12_FEATURE_DATA_D3D12_OPTIONS16 d3d12_options16{}; - auto hr = instance.GetInternal().device->CheckFeatureSupport(D3D12_FEATURE::D3D12_FEATURE_D3D12_OPTIONS16, &d3d12_options16, sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS16)); - supports_gpu_upload = wis::succeeded(hr) && d3d12_options16.GPUUploadHeapSupported; - return {}; - } - -public: - virtual bool Supported() const noexcept override - { - return true; - } - -public: - // may only transition to copy states - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateGPUUploadTexture(const wis::DX12ResourceAllocator& allocator, - wis::TextureDesc desc, - wis::TextureState initial_state = wis::TextureState::Common, - wis::MemoryFlags flags = wis::MemoryFlags::None) const noexcept; - - [[nodiscard]] WIS_INLINE wis::Result - WriteMemoryToSubresourceDirect(const void* host_data, - wis::DX12TextureView dst_texture, - wis::TextureState initial_state, - wis::TextureRegion region) const noexcept; - - [[nodiscard]] bool SupportedDirectGPUUpload(wis::DataFormat) const noexcept - { - return supports_gpu_upload; - } -}; -} // namespace wis - -#endif // WISDOM_DX12 - -#if defined(WISDOM_VULKAN) -#include -#include -#include - -namespace wis { -class VKExtendedAllocation; - -template<> -struct Internal { - wis::SharedDevice device; - h::VkPhysicalDevice adapter; - PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT = nullptr; - PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT = nullptr; - PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2 = nullptr; -}; - -class VKExtendedAllocation : public QueryInternalExtension -{ -protected: - virtual WIS_INLINE bool - GetExtensionInfo(const std::unordered_map>& available_extensions, - std::unordered_set& ext_name_set, - std::unordered_map& structure_map, - std::unordered_map& property_map) noexcept override; - - virtual WIS_INLINE wis::Result - Init(const wis::VKDevice& instance, - const std::unordered_map& structure_map, - const std::unordered_map& property_map) noexcept override; - -public: - virtual bool Supported() const noexcept override - { - return vkCopyMemoryToImageEXT && vkTransitionImageLayoutEXT && vkGetPhysicalDeviceImageFormatProperties2; - } - -public: - // may only transition to copy states - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateGPUUploadTexture(const wis::VKResourceAllocator& allocator, - wis::TextureDesc desc, - wis::TextureState initial_state = wis::TextureState::Common, - wis::MemoryFlags flags = wis::MemoryFlags::None) const noexcept; - - [[nodiscard]] WIS_INLINE wis::Result - WriteMemoryToSubresourceDirect(const void* host_data, - wis::VKTextureView dst_texture, - wis::TextureState initial_state, - wis::TextureRegion region) const noexcept; - - [[nodiscard]] WIS_INLINE bool - SupportedDirectGPUUpload(wis::DataFormat format) const noexcept; -}; -} // namespace wis -#endif // WISDOM_VULKAN - -namespace wis { -#if defined(WISDOM_DX12) && !defined(WISDOM_FORCE_VULKAN) -using ExtendedAllocation = DX12ExtendedAllocation; -#elif defined(WISDOM_VULKAN) -using ExtendedAllocation = VKExtendedAllocation; -#endif // WISDOM_DX12 -} // namespace wis - -#ifndef WISDOM_BUILD_BINARIES -#include "impl/impl.dx.cpp" -#include "impl/impl.vk.cpp" -#endif // !WISDOM_PLATFORM_HEADER_ONLY -#endif // WISDOM_EXTENDED_ALLOCATION_H diff --git a/wisdom/extensions/extended_allocation/wisdom/wisdom_extended_allocation.hpp b/wisdom/extensions/extended_allocation/wisdom/wisdom_extended_allocation.hpp new file mode 100644 index 00000000..23bd9f00 --- /dev/null +++ b/wisdom/extensions/extended_allocation/wisdom/wisdom_extended_allocation.hpp @@ -0,0 +1,250 @@ +#ifndef WISDOM_EXTENDED_ALLOCATION_H +#define WISDOM_EXTENDED_ALLOCATION_H +#if defined(WISDOM_DX12) +#include +#include +#include +#include + +namespace wis { +class DX12ExtendedAllocation; + +template<> +struct Internal { + bool supports_gpu_upload = false; +}; + +class ImplDX12ExtendedAllocation : public QueryInternalExtension +{ +protected: + virtual wis::Result Init(const wis::DX12Device& instance) noexcept override + { + D3D12_FEATURE_DATA_D3D12_OPTIONS16 d3d12_options16{}; + auto hr = instance.GetInternal().device->CheckFeatureSupport(D3D12_FEATURE::D3D12_FEATURE_D3D12_OPTIONS16, &d3d12_options16, sizeof(D3D12_FEATURE_DATA_D3D12_OPTIONS16)); + supports_gpu_upload = wis::succeeded(hr) && d3d12_options16.GPUUploadHeapSupported; + return {}; + } + +public: + virtual bool Supported() const noexcept override + { + return true; + } + +public: + // may only transition to copy states + + [[nodiscard]] WIS_INLINE DX12Texture + CreateGPUUploadTexture(wis::Result& result, const wis::DX12ResourceAllocator& allocator, + wis::TextureDesc desc, + wis::TextureState initial_state = wis::TextureState::Common, + wis::MemoryFlags flags = wis::MemoryFlags::None) const noexcept; + + [[nodiscard]] WIS_INLINE wis::Result + WriteMemoryToSubresourceDirect(const void* host_data, + wis::DX12TextureView dst_texture, + wis::TextureState initial_state, + wis::TextureRegion region) const noexcept; + + [[nodiscard]] bool SupportedDirectGPUUpload(wis::DataFormat) const noexcept + { + return supports_gpu_upload; + } +}; +#pragma region DX12ExtendedAllocation + +class DX12ExtendedAllocation : public wis::ImplDX12ExtendedAllocation +{ +public: + using wis::ImplDX12ExtendedAllocation::ImplDX12ExtendedAllocation; + +public: + /** + * @brief Creates a texture that is optimized for GPU upload. + * Subsequently this texture may be directly mapped and does not require copying through copy queue. + * The memory behaves as GPU local memory. Requires ReBAR enabled in BIOS. + * @param allocator The allocator to create the texture with. + * Allocator must be created by the same device, that initialized this extension. + * @param desc The description of the texture to create. + * @param initial_state The initial state of the texture. Default is Common. + * @param flags The flags of the memory to create the texture with. Default is None. + * @return wis::DX12Texture on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Texture CreateGPUUploadTexture(wis::Result& result, const wis::DX12ResourceAllocator& allocator, const wis::TextureDesc& desc, wis::TextureState initial_state = wis::TextureState::Common, wis::MemoryFlags flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplDX12ExtendedAllocation::CreateGPUUploadTexture(result, allocator, desc, initial_state, flags); + } + /** + * @brief Creates a texture that is optimized for GPU upload. + * Subsequently this texture may be directly mapped and does not require copying through copy queue. + * The memory behaves as GPU local memory. Requires ReBAR enabled in BIOS. + * @param allocator The allocator to create the texture with. + * Allocator must be created by the same device, that initialized this extension. + * @param desc The description of the texture to create. + * @param initial_state The initial state of the texture. Default is Common. + * @param flags The flags of the memory to create the texture with. Default is None. + * @return wis::DX12Texture on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateGPUUploadTexture(const wis::DX12ResourceAllocator& allocator, const wis::TextureDesc& desc, wis::TextureState initial_state = wis::TextureState::Common, wis::MemoryFlags flags = wis::MemoryFlags::None) const noexcept + { + return wis::ResultValue{ &wis::ImplDX12ExtendedAllocation::CreateGPUUploadTexture, this, allocator, desc, initial_state, flags }; + } + /** + * @brief Writes memory directly to the subresource of the texture. + * Subresource is array slice or mip level. + * @param host_data The data to write to the texture. + * @param dst_texture The texture to write the data to. + * @param initial_state The initial state of the texture. + * @param region The region to write the data to. + * */ + [[nodiscard]] inline wis::Result WriteMemoryToSubresourceDirect(const void* host_data, wis::DX12TextureView dst_texture, wis::TextureState initial_state, wis::TextureRegion region) const noexcept + { + return wis::ImplDX12ExtendedAllocation::WriteMemoryToSubresourceDirect(host_data, std::move(dst_texture), initial_state, region); + } + /** + * @brief Check if direct GPU upload is supported for the given format. + * @param format The format to check. + * @return true if direct GPU upload is supported. + * */ + inline bool SupportedDirectGPUUpload(wis::DataFormat format) const noexcept + { + return wis::ImplDX12ExtendedAllocation::SupportedDirectGPUUpload(format); + } +}; +#pragma endregion DX12ExtendedAllocation + +} // namespace wis +#endif // WISDOM_DX12 + +#if defined(WISDOM_VULKAN) +#include +#include +#include + +namespace wis { +class VKExtendedAllocation; + +template<> +struct Internal { + wis::SharedDevice device; + h::VkPhysicalDevice adapter; + PFN_vkCopyMemoryToImageEXT vkCopyMemoryToImageEXT = nullptr; + PFN_vkTransitionImageLayoutEXT vkTransitionImageLayoutEXT = nullptr; + PFN_vkGetPhysicalDeviceImageFormatProperties2KHR vkGetPhysicalDeviceImageFormatProperties2 = nullptr; +}; + +class ImplVKExtendedAllocation : public QueryInternalExtension +{ +protected: + virtual WIS_INLINE bool + GetExtensionInfo(const std::unordered_map>& available_extensions, + std::unordered_set& ext_name_set, + std::unordered_map& structure_map, + std::unordered_map& property_map) noexcept override; + + virtual WIS_INLINE wis::Result + Init(const wis::VKDevice& instance, + const std::unordered_map& structure_map, + const std::unordered_map& property_map) noexcept override; + +public: + virtual bool Supported() const noexcept override + { + return vkCopyMemoryToImageEXT && vkTransitionImageLayoutEXT && vkGetPhysicalDeviceImageFormatProperties2; + } + +public: + // may only transition to copy states + [[nodiscard]] WIS_INLINE wis::VKTexture + CreateGPUUploadTexture(wis::Result& result, const wis::VKResourceAllocator& allocator, + wis::TextureDesc desc, + wis::TextureState initial_state = wis::TextureState::Common, + wis::MemoryFlags flags = wis::MemoryFlags::None) const noexcept; + + [[nodiscard]] WIS_INLINE wis::Result + WriteMemoryToSubresourceDirect(const void* host_data, + wis::VKTextureView dst_texture, + wis::TextureState initial_state, + wis::TextureRegion region) const noexcept; + + [[nodiscard]] WIS_INLINE bool + SupportedDirectGPUUpload(wis::DataFormat format) const noexcept; +}; +#pragma region VKExtendedAllocation + +class VKExtendedAllocation : public wis::ImplVKExtendedAllocation +{ +public: + using wis::ImplVKExtendedAllocation::ImplVKExtendedAllocation; + +public: + /** + * @brief Creates a texture that is optimized for GPU upload. + * Subsequently this texture may be directly mapped and does not require copying through copy queue. + * The memory behaves as GPU local memory. Requires ReBAR enabled in BIOS. + * @param allocator The allocator to create the texture with. + * Allocator must be created by the same device, that initialized this extension. + * @param desc The description of the texture to create. + * @param initial_state The initial state of the texture. Default is Common. + * @param flags The flags of the memory to create the texture with. Default is None. + * @return wis::VKTexture on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKTexture CreateGPUUploadTexture(wis::Result& result, const wis::VKResourceAllocator& allocator, const wis::TextureDesc& desc, wis::TextureState initial_state = wis::TextureState::Common, wis::MemoryFlags flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplVKExtendedAllocation::CreateGPUUploadTexture(result, allocator, desc, initial_state, flags); + } + /** + * @brief Creates a texture that is optimized for GPU upload. + * Subsequently this texture may be directly mapped and does not require copying through copy queue. + * The memory behaves as GPU local memory. Requires ReBAR enabled in BIOS. + * @param allocator The allocator to create the texture with. + * Allocator must be created by the same device, that initialized this extension. + * @param desc The description of the texture to create. + * @param initial_state The initial state of the texture. Default is Common. + * @param flags The flags of the memory to create the texture with. Default is None. + * @return wis::VKTexture on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateGPUUploadTexture(const wis::VKResourceAllocator& allocator, const wis::TextureDesc& desc, wis::TextureState initial_state = wis::TextureState::Common, wis::MemoryFlags flags = wis::MemoryFlags::None) const noexcept + { + return wis::ResultValue{ &wis::ImplVKExtendedAllocation::CreateGPUUploadTexture, this, allocator, desc, initial_state, flags }; + } + /** + * @brief Writes memory directly to the subresource of the texture. + * Subresource is array slice or mip level. + * @param host_data The data to write to the texture. + * @param dst_texture The texture to write the data to. + * @param initial_state The initial state of the texture. + * @param region The region to write the data to. + * */ + [[nodiscard]] inline wis::Result WriteMemoryToSubresourceDirect(const void* host_data, wis::VKTextureView dst_texture, wis::TextureState initial_state, wis::TextureRegion region) const noexcept + { + return wis::ImplVKExtendedAllocation::WriteMemoryToSubresourceDirect(host_data, std::move(dst_texture), initial_state, region); + } + /** + * @brief Check if direct GPU upload is supported for the given format. + * @param format The format to check. + * @return true if direct GPU upload is supported. + * */ + inline bool SupportedDirectGPUUpload(wis::DataFormat format) const noexcept + { + return wis::ImplVKExtendedAllocation::SupportedDirectGPUUpload(format); + } +}; +#pragma endregion VKExtendedAllocation + +} // namespace wis +#endif // WISDOM_VULKAN + +namespace wis { +#if defined(WISDOM_DX12) && !defined(WISDOM_FORCE_VULKAN) +using ExtendedAllocation = DX12ExtendedAllocation; +#elif defined(WISDOM_VULKAN) +using ExtendedAllocation = VKExtendedAllocation; +#endif // WISDOM_DX12 +} // namespace wis + +#ifndef WISDOM_BUILD_BINARIES +#include "impl/impl.dx.cpp" +#include "impl/impl.vk.cpp" +#endif // !WISDOM_PLATFORM_HEADER_ONLY +#endif // WISDOM_EXTENDED_ALLOCATION_H diff --git a/wisdom/include/wisdom/dx12/dx12_adapter.h b/wisdom/include/wisdom/dx12/dx12_adapter.h index 0bdb2075..c60fdf0d 100644 --- a/wisdom/include/wisdom/dx12/dx12_adapter.h +++ b/wisdom/include/wisdom/dx12/dx12_adapter.h @@ -1,11 +1,7 @@ #ifndef WIS_DX12_ADAPTER_H #define WIS_DX12_ADAPTER_H -#include -#include -#include #include -#include -#include +#include namespace wis { class DX12Adapter; @@ -19,8 +15,6 @@ class ImplDX12Adapter : public QueryInternal { public: ImplDX12Adapter() noexcept = default; - explicit ImplDX12Adapter(wis::com_ptr adapter) noexcept - : QueryInternal(std::move(adapter)) { } operator bool() const noexcept { return bool(adapter); @@ -29,15 +23,17 @@ class ImplDX12Adapter : public QueryInternal public: [[nodiscard]] wis::Result GetDesc(AdapterDesc* pout_desc) const noexcept { - if (!pout_desc) + if (!pout_desc) { return wis::make_result(E_INVALIDARG); + } auto& out_desc = *pout_desc; DXGI_ADAPTER_DESC1 desc; auto hr = adapter->GetDesc1(&desc); - if (!wis::succeeded(hr)) + if (!wis::succeeded(hr)) { return wis::make_result(hr); + } auto description = wis::to_string(desc.Description); std::strncpy(const_cast(out_desc.description.data()), description.c_str(), diff --git a/wisdom/include/wisdom/dx12/dx12_allocator.h b/wisdom/include/wisdom/dx12/dx12_allocator.h index fe79783f..0a454aeb 100644 --- a/wisdom/include/wisdom/dx12/dx12_allocator.h +++ b/wisdom/include/wisdom/dx12/dx12_allocator.h @@ -1,7 +1,6 @@ #ifndef WIS_DX12_ALLOCATOR_H #define WIS_DX12_ALLOCATOR_H #include -#include namespace wis { class DX12ResourceAllocator; @@ -18,10 +17,6 @@ class ImplDX12ResourceAllocator : public QueryInternal { public: ImplDX12ResourceAllocator() = default; - explicit ImplDX12ResourceAllocator(wis::com_ptr in_allocator, ID3D12Device10* device) noexcept - : QueryInternal(std::move(in_allocator), device) - { - } operator bool() const noexcept { return bool(allocator); @@ -29,11 +24,11 @@ class ImplDX12ResourceAllocator : public QueryInternal public: // Resource creation functions - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateBuffer(uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12Buffer + CreateBuffer(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateTexture(const wis::TextureDesc& desc, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; + [[nodiscard]] WIS_INLINE DX12Texture + CreateTexture(wis::Result& result, const wis::TextureDesc& desc, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; // Allocation info functions [[nodiscard]] WIS_INLINE wis::AllocationInfo @@ -43,39 +38,39 @@ class ImplDX12ResourceAllocator : public QueryInternal GetBufferAllocationInfo(uint64_t size, BufferUsage flags = BufferUsage::None) const noexcept; // Allocation functions - [[nodiscard]] WIS_INLINE wis::ResultValue - AllocateTextureMemory(uint64_t size, wis::TextureUsage usage, + [[nodiscard]] WIS_INLINE DX12Memory + AllocateTextureMemory(wis::Result& result, uint64_t size, wis::TextureUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - AllocateBufferMemory(uint64_t size, wis::BufferUsage usage, + [[nodiscard]] WIS_INLINE DX12Memory + AllocateBufferMemory(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; // Resource placement functions - [[nodiscard]] WIS_INLINE wis::ResultValue - PlaceBuffer(DX12MemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept; + [[nodiscard]] WIS_INLINE DX12Buffer + PlaceBuffer(wis::Result& result, DX12MemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - PlaceTexture(DX12MemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept; + [[nodiscard]] WIS_INLINE DX12Texture + PlaceTexture(wis::Result& result, DX12MemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept; public: // Convenience functions - [[nodiscard]] wis::ResultValue - CreateUploadBuffer(uint64_t size) const noexcept + [[nodiscard]] DX12Buffer + CreateUploadBuffer(wis::Result& result, uint64_t size) const noexcept { - return CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped); + return CreateBuffer(result, size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped); } - [[nodiscard]] wis::ResultValue - CreateReadbackBuffer(uint64_t size) const noexcept + [[nodiscard]] DX12Buffer + CreateReadbackBuffer(wis::Result& result, uint64_t size) const noexcept { - return CreateBuffer(size, BufferUsage::CopyDst, MemoryType::Readback, wis::MemoryFlags::Mapped); + return CreateBuffer(result, size, BufferUsage::CopyDst, MemoryType::Readback, wis::MemoryFlags::Mapped); } public: - [[nodiscard]] WIS_INLINE wis::ResultValue - DX12CreateResource(const D3D12MA::ALLOCATION_DESC& all_desc, const D3D12_RESOURCE_DESC1& res_desc, D3D12_RESOURCE_STATES state) const noexcept; + [[nodiscard]] WIS_INLINE DX12Buffer + DX12CreateResource(wis::Result& result, const D3D12MA::ALLOCATION_DESC& all_desc, const D3D12_RESOURCE_DESC1& res_desc, D3D12_RESOURCE_STATES state) const noexcept; WIS_INLINE static void DX12FillBufferDesc(uint64_t size, BufferUsage flags, D3D12_RESOURCE_DESC1& info) noexcept; @@ -95,6 +90,19 @@ class DX12ResourceAllocator : public wis::ImplDX12ResourceAllocator using wis::ImplDX12ResourceAllocator::ImplDX12ResourceAllocator; public: + /** + * @brief Creates a buffer object and allocates memory for it. + * Equivalent to creating a Buffer, allocating a memory and binding buffer to it. + * @param size The size of the buffer in bytes. + * @param usage The usage of the buffer. May affect the alignment of the buffer memory allocation. + * @param memory The type of the memory to allocate for the buffer. + * @param mem_flags The flags of the memory to allocate for the buffer. + * @return wis::DX12Buffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Buffer CreateBuffer(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplDX12ResourceAllocator::CreateBuffer(result, size, usage, memory, mem_flags); + } /** * @brief Creates a buffer object and allocates memory for it. * Equivalent to creating a Buffer, allocating a memory and binding buffer to it. @@ -106,7 +114,19 @@ class DX12ResourceAllocator : public wis::ImplDX12ResourceAllocator * */ [[nodiscard]] inline wis::ResultValue CreateBuffer(uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept { - return wis::ImplDX12ResourceAllocator::CreateBuffer(size, usage, memory, mem_flags); + return wis::ResultValue{ &wis::ImplDX12ResourceAllocator::CreateBuffer, this, size, usage, memory, mem_flags }; + } + /** + * @brief Creates a texture object and allocates memory for it. + * Equivalent to creating a Texture, allocating a memory and binding texture to it. + * @param desc The description of the texture to create. + * @param memory The type of the memory to allocate for the texture. + * @param mem_flags The flags of the memory to allocate for the texture. + * @return wis::DX12Texture on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Texture CreateTexture(wis::Result& result, const wis::TextureDesc& desc, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplDX12ResourceAllocator::CreateTexture(result, desc, memory, mem_flags); } /** * @brief Creates a texture object and allocates memory for it. @@ -118,7 +138,47 @@ class DX12ResourceAllocator : public wis::ImplDX12ResourceAllocator * */ [[nodiscard]] inline wis::ResultValue CreateTexture(const wis::TextureDesc& desc, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept { - return wis::ImplDX12ResourceAllocator::CreateTexture(desc, memory, mem_flags); + return wis::ResultValue{ &wis::ImplDX12ResourceAllocator::CreateTexture, this, desc, memory, mem_flags }; + } + /** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param size The size of the buffer in bytes. + * @return wis::DX12Buffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Buffer CreateUploadBuffer(wis::Result& result, uint64_t size) const noexcept + { + return wis::ImplDX12ResourceAllocator::CreateUploadBuffer(result, size); + } + /** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param size The size of the buffer in bytes. + * @return wis::DX12Buffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateUploadBuffer(uint64_t size) const noexcept + { + return wis::ResultValue{ &wis::ImplDX12ResourceAllocator::CreateUploadBuffer, this, size }; + } + /** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param size The size of the buffer in bytes. + * @return wis::DX12Buffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Buffer CreateReadbackBuffer(wis::Result& result, uint64_t size) const noexcept + { + return wis::ImplDX12ResourceAllocator::CreateReadbackBuffer(result, size); + } + /** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param size The size of the buffer in bytes. + * @return wis::DX12Buffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateReadbackBuffer(uint64_t size) const noexcept + { + return wis::ResultValue{ &wis::ImplDX12ResourceAllocator::CreateReadbackBuffer, this, size }; } /** * @brief Returns the allocation info for the texture. @@ -139,6 +199,18 @@ class DX12ResourceAllocator : public wis::ImplDX12ResourceAllocator { return wis::ImplDX12ResourceAllocator::GetBufferAllocationInfo(size, usage); } + /** + * @brief Allocates memory for the image. + * @param size The size of the memory to allocate. + * @param usage The usage of the image memory. + * @param mem_type The type of the memory to allocate for the image. + * @param mem_flags The flags of the memory to allocate for the image. + * @return wis::DX12Memory on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Memory AllocateTextureMemory(wis::Result& result, uint64_t size, wis::TextureUsage usage, wis::MemoryType mem_type = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplDX12ResourceAllocator::AllocateTextureMemory(result, size, usage, mem_type, mem_flags); + } /** * @brief Allocates memory for the image. * @param size The size of the memory to allocate. @@ -149,7 +221,19 @@ class DX12ResourceAllocator : public wis::ImplDX12ResourceAllocator * */ [[nodiscard]] inline wis::ResultValue AllocateTextureMemory(uint64_t size, wis::TextureUsage usage, wis::MemoryType mem_type = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept { - return wis::ImplDX12ResourceAllocator::AllocateTextureMemory(size, usage, mem_type, mem_flags); + return wis::ResultValue{ &wis::ImplDX12ResourceAllocator::AllocateTextureMemory, this, size, usage, mem_type, mem_flags }; + } + /** + * @brief Allocates memory for the buffer. + * @param size The size of the memory to allocate. + * @param usage The usage of the buffer memory. + * @param mem_type The type of the memory to allocate for the buffer. + * @param mem_flags The flags of the memory to allocate for the buffer. + * @return wis::DX12Memory on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Memory AllocateBufferMemory(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType mem_type = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplDX12ResourceAllocator::AllocateBufferMemory(result, size, usage, mem_type, mem_flags); } /** * @brief Allocates memory for the buffer. @@ -161,7 +245,21 @@ class DX12ResourceAllocator : public wis::ImplDX12ResourceAllocator * */ [[nodiscard]] inline wis::ResultValue AllocateBufferMemory(uint64_t size, wis::BufferUsage usage, wis::MemoryType mem_type = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept { - return wis::ImplDX12ResourceAllocator::AllocateBufferMemory(size, usage, mem_type, mem_flags); + return wis::ResultValue{ &wis::ImplDX12ResourceAllocator::AllocateBufferMemory, this, size, usage, mem_type, mem_flags }; + } + /** + * @brief Creates buffer with provided memory. + * Equivalent to creating aliasing resource. + * Note, the resulting buffer must be destroyed before Memory backing it up. + * @param memory The memory to bind the buffer to. + * @param memory_offset The offset in the memory to bind the buffer to. + * @param size The size of the buffer to bind. + * @param usage The usage of the buffer. + * @return wis::DX12Buffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Buffer PlaceBuffer(wis::Result& result, wis::DX12MemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept + { + return wis::ImplDX12ResourceAllocator::PlaceBuffer(result, std::move(memory), memory_offset, size, usage); } /** * @brief Creates buffer with provided memory. @@ -175,7 +273,20 @@ class DX12ResourceAllocator : public wis::ImplDX12ResourceAllocator * */ [[nodiscard]] inline wis::ResultValue PlaceBuffer(wis::DX12MemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept { - return wis::ImplDX12ResourceAllocator::PlaceBuffer(std::move(memory), memory_offset, size, usage); + return wis::ResultValue{ &wis::ImplDX12ResourceAllocator::PlaceBuffer, this, std::move(memory), memory_offset, size, usage }; + } + /** + * @brief Creates texture with provided memory. + * Equivalent to creating aliasing resource. + * Note, the resulting Texture must be destroyed before Memory backing it up. + * @param memory The memory to bind the buffer to. + * @param memory_offset The offset in the memory to bind the texture to. + * @param desc The description of the texture to create. + * @return wis::DX12Texture on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Texture PlaceTexture(wis::Result& result, wis::DX12MemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept + { + return wis::ImplDX12ResourceAllocator::PlaceTexture(result, std::move(memory), memory_offset, desc); } /** * @brief Creates texture with provided memory. @@ -188,7 +299,7 @@ class DX12ResourceAllocator : public wis::ImplDX12ResourceAllocator * */ [[nodiscard]] inline wis::ResultValue PlaceTexture(wis::DX12MemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept { - return wis::ImplDX12ResourceAllocator::PlaceTexture(std::move(memory), memory_offset, desc); + return wis::ResultValue{ &wis::ImplDX12ResourceAllocator::PlaceTexture, this, std::move(memory), memory_offset, desc }; } }; #pragma endregion DX12ResourceAllocator diff --git a/wisdom/include/wisdom/dx12/dx12_checks.h b/wisdom/include/wisdom/dx12/dx12_checks.h index 520d9caa..b070e3b5 100644 --- a/wisdom/include/wisdom/dx12/dx12_checks.h +++ b/wisdom/include/wisdom/dx12/dx12_checks.h @@ -1,6 +1,5 @@ #ifndef WIS_DX12_CHECKS_H #define WIS_DX12_CHECKS_H -#include #include #include #include @@ -18,16 +17,18 @@ inline void log_dxgi_errors() noexcept /// @return True if the HRESULT is a success code inline bool succeeded(HRESULT hr) noexcept { - if constexpr (debug_layer) + if constexpr (debug_layer) { log_dxgi_errors(); + } return hr >= 0; } /// @brief Check if there are any errors in the current context, logging any errors inline void check_context() noexcept { - if constexpr (debug_layer) + if constexpr (debug_layer) { log_dxgi_errors(); + } } template diff --git a/wisdom/include/wisdom/dx12/dx12_command_list.h b/wisdom/include/wisdom/dx12/dx12_command_list.h index 24b5b481..9be5f50b 100644 --- a/wisdom/include/wisdom/dx12/dx12_command_list.h +++ b/wisdom/include/wisdom/dx12/dx12_command_list.h @@ -1,7 +1,6 @@ #ifndef WIS_DX12_COMMAND_LIST_H #define WIS_DX12_COMMAND_LIST_H #include -#include #include #include @@ -25,11 +24,6 @@ class ImplDX12CommandList : public QueryInternal { public: ImplDX12CommandList() noexcept = default; - explicit ImplDX12CommandList(wis::com_ptr allocator, - wis::com_ptr list) noexcept - : QueryInternal(std::move(allocator), std::move(list)) - { - } operator bool() const noexcept { return bool(list); @@ -152,7 +146,7 @@ class DX12CommandList : public wis::ImplDX12CommandList * @param destination The destination buffer to copy to. * @param region The region to copy. * */ - inline void CopyBuffer(wis::DX12BufferView source, wis::DX12BufferView destination, wis::BufferRegion region) noexcept + inline void CopyBuffer(wis::DX12BufferView source, wis::DX12BufferView destination, const wis::BufferRegion& region) noexcept { wis::ImplDX12CommandList::CopyBuffer(std::move(source), std::move(destination), region); } @@ -183,7 +177,7 @@ class DX12CommandList : public wis::ImplDX12CommandList * @param barrier The barrier to set. * @param buffer The buffer to set the barrier on. * */ - inline void BufferBarrier(wis::BufferBarrier barrier, wis::DX12BufferView buffer) noexcept + inline void BufferBarrier(const wis::BufferBarrier& barrier, wis::DX12BufferView buffer) noexcept { wis::ImplDX12CommandList::BufferBarrier(barrier, std::move(buffer)); } @@ -201,7 +195,7 @@ class DX12CommandList : public wis::ImplDX12CommandList * @param barrier The barrier to set. * @param texture The texture to set the barrier on. * */ - inline void TextureBarrier(wis::TextureBarrier barrier, wis::DX12TextureView texture) noexcept + inline void TextureBarrier(const wis::TextureBarrier& barrier, wis::DX12TextureView texture) noexcept { wis::ImplDX12CommandList::TextureBarrier(barrier, std::move(texture)); } @@ -282,7 +276,7 @@ class DX12CommandList : public wis::ImplDX12CommandList * @brief Sets the viewport. * @param viewport The viewport to set. * */ - inline void RSSetViewport(wis::Viewport viewport) noexcept + inline void RSSetViewport(const wis::Viewport& viewport) noexcept { wis::ImplDX12CommandList::RSSetViewport(viewport); } @@ -299,7 +293,7 @@ class DX12CommandList : public wis::ImplDX12CommandList * @brief Sets the scissor rect. * @param scissor The scissor to set. * */ - inline void RSSetScissor(wis::Scissor scissor) noexcept + inline void RSSetScissor(const wis::Scissor& scissor) noexcept { wis::ImplDX12CommandList::RSSetScissor(scissor); } diff --git a/wisdom/include/wisdom/dx12/dx12_command_queue.h b/wisdom/include/wisdom/dx12/dx12_command_queue.h index 03a1e0b2..4014fad7 100644 --- a/wisdom/include/wisdom/dx12/dx12_command_queue.h +++ b/wisdom/include/wisdom/dx12/dx12_command_queue.h @@ -17,9 +17,6 @@ class ImplDX12CommandQueue : public QueryInternal { public: ImplDX12CommandQueue() = default; - explicit ImplDX12CommandQueue(wis::com_ptr queue) noexcept - : QueryInternal(std::move(queue)) { } - operator bool() const noexcept { return bool(queue); diff --git a/wisdom/include/wisdom/dx12/dx12_convert.h b/wisdom/include/wisdom/dx12/dx12_convert.h index 4ab665e1..4023acb5 100644 --- a/wisdom/include/wisdom/dx12/dx12_convert.h +++ b/wisdom/include/wisdom/dx12/dx12_convert.h @@ -2,7 +2,7 @@ #define WIS_DX12_CONVERT_H #include #include -#include +#include namespace wis { inline constexpr wis::Status convert(HRESULT hr) noexcept diff --git a/wisdom/include/wisdom/dx12/dx12_descriptor_storage.h b/wisdom/include/wisdom/dx12/dx12_descriptor_storage.h index 5949d6d1..d6cced46 100644 --- a/wisdom/include/wisdom/dx12/dx12_descriptor_storage.h +++ b/wisdom/include/wisdom/dx12/dx12_descriptor_storage.h @@ -29,11 +29,6 @@ class ImplDX12DescriptorStorage : public QueryInternal { public: ImplDX12DescriptorStorage() = default; - explicit ImplDX12DescriptorStorage(Internal&& internal) noexcept - : QueryInternal(std::move(internal)) - { - } - operator bool() const noexcept { return bool(heap_resource) || bool(heap_sampler); diff --git a/wisdom/include/wisdom/dx12/dx12_device.h b/wisdom/include/wisdom/dx12/dx12_device.h index de45433b..73fa291e 100644 --- a/wisdom/include/wisdom/dx12/dx12_device.h +++ b/wisdom/include/wisdom/dx12/dx12_device.h @@ -26,10 +26,9 @@ class ImplDX12Device : public QueryInternal { public: ImplDX12Device() noexcept = default; - explicit ImplDX12Device(wis::com_ptr device, wis::com_ptr adapter, wis::com_ptr factory) noexcept - : QueryInternal(std::move(device), std::move(adapter), std::move(factory)) - { - } + ImplDX12Device(ImplDX12Device&&) noexcept = default; + ImplDX12Device& operator=(ImplDX12Device&&) noexcept = default; + operator bool() const noexcept { return bool(device); @@ -43,52 +42,54 @@ class ImplDX12Device : public QueryInternal MutiWaitFlags wait_all = MutiWaitFlags::All, uint64_t timeout = std::numeric_limits::max()) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateFence(uint64_t initial_value = 0ull, wis::FenceFlags flags = wis::FenceFlags::None) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12Fence + CreateFence(wis::Result& result, uint64_t initial_value = 0ull, wis::FenceFlags flags = wis::FenceFlags::None) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateCommandQueue(wis::QueueType type) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12CommandQueue + CreateCommandQueue(wis::Result& result, wis::QueueType type) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateCommandList(wis::QueueType type) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12CommandList + CreateCommandList(wis::Result& result, wis::QueueType type) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateGraphicsPipeline(const wis::DX12GraphicsPipelineDesc* desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12PipelineState + CreateGraphicsPipeline(wis::Result& result, const wis::DX12GraphicsPipelineDesc& desc) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateShader(void* data, size_t size) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12Shader + CreateShader(wis::Result& result, void* data, size_t size) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateAllocator() const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12ResourceAllocator + CreateAllocator(wis::Result& result) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateRenderTarget(DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12RenderTarget + CreateRenderTarget(wis::Result& result, DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateDepthStencilTarget(DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12RenderTarget + CreateDepthStencilTarget(wis::Result& result, DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateSampler(const wis::SamplerDesc* desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12Sampler + CreateSampler(wis::Result& result, const wis::SamplerDesc& desc) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateShaderResource(DX12TextureView texture, wis::ShaderResourceDesc desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12ShaderResource + CreateShaderResource(wis::Result& result, DX12TextureView texture, wis::ShaderResourceDesc desc) const noexcept; // returns true only for now [[nodiscard]] WIS_INLINE bool QueryFeatureSupport(wis::DeviceFeature feature) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateDescriptorStorage(wis::DescriptorStorageDesc desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12DescriptorStorage + CreateDescriptorStorage(wis::Result& result, const wis::DescriptorStorageDesc& desc) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateRootSignature(const PushConstant* constants = nullptr, + [[nodiscard]] WIS_INLINE wis::DX12RootSignature + CreateRootSignature(wis::Result& result, + const PushConstant* constants = nullptr, uint32_t constants_size = 0, const PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_size = 0, uint32_t space_overlap_count = 1) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateRootSignature2(const wis::PushConstant* push_constants = nullptr, + [[nodiscard]] WIS_INLINE wis::DX12RootSignature + CreateRootSignature2(wis::Result& result, + const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_count = 0, @@ -124,6 +125,16 @@ class DX12Device : public wis::ImplDX12Device { return wis::ImplDX12Device::WaitForMultipleFences(fences, fence_values, fence_count, wait_all, timeout); } + /** + * @brief Creates a fence with initial value and flags. + * @param initial_value The initial value of the fence. + * @param flags The flags of the fence. + * @return wis::DX12Fence on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Fence CreateFence(wis::Result& result, uint64_t initial_value = 0, wis::FenceFlags flags = wis::FenceFlags::None) const noexcept + { + return wis::ImplDX12Device::CreateFence(result, initial_value, flags); + } /** * @brief Creates a fence with initial value and flags. * @param initial_value The initial value of the fence. @@ -132,7 +143,16 @@ class DX12Device : public wis::ImplDX12Device * */ [[nodiscard]] inline wis::ResultValue CreateFence(uint64_t initial_value = 0, wis::FenceFlags flags = wis::FenceFlags::None) const noexcept { - return wis::ImplDX12Device::CreateFence(initial_value, flags); + return wis::ResultValue{ &wis::ImplDX12Device::CreateFence, this, initial_value, flags }; + } + /** + * @brief Creates a command queue with specified type. + * @param type The type of the queue to create. + * @return wis::DX12CommandQueue on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12CommandQueue CreateCommandQueue(wis::Result& result, wis::QueueType type) const noexcept + { + return wis::ImplDX12Device::CreateCommandQueue(result, type); } /** * @brief Creates a command queue with specified type. @@ -141,7 +161,16 @@ class DX12Device : public wis::ImplDX12Device * */ [[nodiscard]] inline wis::ResultValue CreateCommandQueue(wis::QueueType type) const noexcept { - return wis::ImplDX12Device::CreateCommandQueue(type); + return wis::ResultValue{ &wis::ImplDX12Device::CreateCommandQueue, this, type }; + } + /** + * @brief Creates a command list for specific queue type. + * @param type The type of the queue to create the command list for. + * @return wis::DX12CommandList on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12CommandList CreateCommandList(wis::Result& result, wis::QueueType type) const noexcept + { + return wis::ImplDX12Device::CreateCommandList(result, type); } /** * @brief Creates a command list for specific queue type. @@ -150,16 +179,44 @@ class DX12Device : public wis::ImplDX12Device * */ [[nodiscard]] inline wis::ResultValue CreateCommandList(wis::QueueType type) const noexcept { - return wis::ImplDX12Device::CreateCommandList(type); + return wis::ResultValue{ &wis::ImplDX12Device::CreateCommandList, this, type }; + } + /** + * @brief Creates a graphics pipeline state object. + * @param desc The description of the graphics pipeline to create. + * @return wis::DX12PipelineState on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12PipelineState CreateGraphicsPipeline(wis::Result& result, const wis::DX12GraphicsPipelineDesc& desc) const noexcept + { + return wis::ImplDX12Device::CreateGraphicsPipeline(result, desc); } /** * @brief Creates a graphics pipeline state object. * @param desc The description of the graphics pipeline to create. * @return wis::DX12PipelineState on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateGraphicsPipeline(const wis::DX12GraphicsPipelineDesc* desc) const noexcept + [[nodiscard]] inline wis::ResultValue CreateGraphicsPipeline(const wis::DX12GraphicsPipelineDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplDX12Device::CreateGraphicsPipeline, this, desc }; + } + /** + * @brief Creates a root signature object for use with DescriptorStorage. + * @param push_constants The root constants to create the root signature with. + * @param constants_count The number of push constants. Max is 5. + * @param push_descriptors The root descriptors to create the root signature with. + * In shader will appear in order of submission. e.g. push_descriptors[5] is [[vk::binding(5,0)]] ... : register(b5/t5/u5) + * @param descriptors_count The number of push descriptors. Max is 8. + * @param space_overlap_count Count of descriptor spaces to overlap for each of the DescriptorStorage types. + * Default is 1. Max is 16. This is used primarily for descriptor type aliasing. + * Example: If wis::DX12Device is 2, that means that 2 descriptor spaces will be allocated for each descriptor type. + * [[vk::binding(0,0)]] SamplerState samplers: register(s0,space1); // space1 can be used for different type of samplers e.g. SamplerComparisonState + * [[vk::binding(0,0)]] SamplerComparisonState shadow_samplers: register(s0,space2); // they use the same binding (works like overloading) + * [[vk::binding(0,1)]] ConstantBuffer cbuffers: register(b0,space3); // this type also has 2 spaces, next will be on space 4 etc. + * @return wis::DX12RootSignature on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12RootSignature CreateRootSignature(wis::Result& result, const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t descriptors_count = 0, uint32_t space_overlap_count = 1) const noexcept { - return wis::ImplDX12Device::CreateGraphicsPipeline(desc); + return wis::ImplDX12Device::CreateRootSignature(result, push_constants, constants_count, push_descriptors, descriptors_count, space_overlap_count); } /** * @brief Creates a root signature object for use with DescriptorStorage. @@ -178,7 +235,23 @@ class DX12Device : public wis::ImplDX12Device * */ [[nodiscard]] inline wis::ResultValue CreateRootSignature(const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t descriptors_count = 0, uint32_t space_overlap_count = 1) const noexcept { - return wis::ImplDX12Device::CreateRootSignature(push_constants, constants_count, push_descriptors, descriptors_count, space_overlap_count); + return wis::ResultValue{ &wis::ImplDX12Device::CreateRootSignature, this, push_constants, constants_count, push_descriptors, descriptors_count, space_overlap_count }; + } + /** + * @brief Creates a root signature object for use with DescriptorStorage. + * Supplies number of types for each descriptor type separately. + * @param push_constants The root constants to create the root signature with. + * @param constants_count The number of push constants. Max is 5. + * @param push_descriptors The root descriptors to create the root signature with. + * In shader will appear in order of submission. e.g. root_descriptors[5] is [[vk::binding(5,0)]] ... : register(b5/t5/u5) + * @param push_descriptors_count The number of push descriptors. Max is 8. + * @param descriptor_spacing Descriptor spacing allocation. + * nullptr means allocate 1 space for each. + * @return wis::DX12RootSignature on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12RootSignature CreateRootSignature2(wis::Result& result, const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_count = 0, const wis::DescriptorSpacing* descriptor_spacing = nullptr) const noexcept + { + return wis::ImplDX12Device::CreateRootSignature2(result, push_constants, constants_count, push_descriptors, push_descriptors_count, descriptor_spacing); } /** * @brief Creates a root signature object for use with DescriptorStorage. @@ -194,7 +267,17 @@ class DX12Device : public wis::ImplDX12Device * */ [[nodiscard]] inline wis::ResultValue CreateRootSignature2(const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_count = 0, const wis::DescriptorSpacing* descriptor_spacing = nullptr) const noexcept { - return wis::ImplDX12Device::CreateRootSignature2(push_constants, constants_count, push_descriptors, push_descriptors_count, descriptor_spacing); + return wis::ResultValue{ &wis::ImplDX12Device::CreateRootSignature2, this, push_constants, constants_count, push_descriptors, push_descriptors_count, descriptor_spacing }; + } + /** + * @brief Creates a shader object. + * @param data Shader bytecode. + * @param size The size of the shader data in bytes. For SPIR-V must be multiple of 4. + * @return wis::DX12Shader on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Shader CreateShader(wis::Result& result, void* data, uint32_t size) const noexcept + { + return wis::ImplDX12Device::CreateShader(result, data, size); } /** * @brief Creates a shader object. @@ -204,7 +287,15 @@ class DX12Device : public wis::ImplDX12Device * */ [[nodiscard]] inline wis::ResultValue CreateShader(void* data, uint32_t size) const noexcept { - return wis::ImplDX12Device::CreateShader(data, size); + return wis::ResultValue{ &wis::ImplDX12Device::CreateShader, this, data, size }; + } + /** + * @brief Creates a resource allocator object. + * @return wis::DX12ResourceAllocator on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12ResourceAllocator CreateAllocator(wis::Result& result) const noexcept + { + return wis::ImplDX12Device::CreateAllocator(result); } /** * @brief Creates a resource allocator object. @@ -212,7 +303,10 @@ class DX12Device : public wis::ImplDX12Device * */ [[nodiscard]] inline wis::ResultValue CreateAllocator() const noexcept { - return wis::ImplDX12Device::CreateAllocator(); + return wis::ResultValue{ + &wis::ImplDX12Device::CreateAllocator, + this, + }; } /** * @brief Creates a render target object. @@ -220,9 +314,19 @@ class DX12Device : public wis::ImplDX12Device * @param desc The description of the render target to create. * @return wis::DX12RenderTarget on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateRenderTarget(wis::DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept + [[nodiscard]] inline wis::DX12RenderTarget CreateRenderTarget(wis::Result& result, wis::DX12TextureView texture, const wis::RenderTargetDesc& desc) const noexcept { - return wis::ImplDX12Device::CreateRenderTarget(std::move(texture), desc); + return wis::ImplDX12Device::CreateRenderTarget(result, std::move(texture), desc); + } + /** + * @brief Creates a render target object. + * @param texture The texture view to create the render target with. + * @param desc The description of the render target to create. + * @return wis::DX12RenderTarget on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateRenderTarget(wis::DX12TextureView texture, const wis::RenderTargetDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplDX12Device::CreateRenderTarget, this, std::move(texture), desc }; } /** * @brief Creates a depth stencil target object. @@ -233,18 +337,40 @@ class DX12Device : public wis::ImplDX12Device * Does not work with 3D textures. * @return wis::DX12RenderTarget on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateDepthStencilTarget(wis::DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept + [[nodiscard]] inline wis::DX12RenderTarget CreateDepthStencilTarget(wis::Result& result, wis::DX12TextureView texture, const wis::RenderTargetDesc& desc) const noexcept { - return wis::ImplDX12Device::CreateDepthStencilTarget(std::move(texture), desc); + return wis::ImplDX12Device::CreateDepthStencilTarget(result, std::move(texture), desc); + } + /** + * @brief Creates a depth stencil target object. + * Works only with depth formats. + * Used with render passes. + * @param texture The texture view to create the render target with. + * @param desc The description of the render target to create. + * Does not work with 3D textures. + * @return wis::DX12RenderTarget on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateDepthStencilTarget(wis::DX12TextureView texture, const wis::RenderTargetDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplDX12Device::CreateDepthStencilTarget, this, std::move(texture), desc }; } /** * @brief Creates a sampler object. * @param desc The description of the sampler to create. * @return wis::DX12Sampler on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateSampler(const wis::SamplerDesc* desc) const noexcept + [[nodiscard]] inline wis::DX12Sampler CreateSampler(wis::Result& result, const wis::SamplerDesc& desc) const noexcept { - return wis::ImplDX12Device::CreateSampler(desc); + return wis::ImplDX12Device::CreateSampler(result, desc); + } + /** + * @brief Creates a sampler object. + * @param desc The description of the sampler to create. + * @return wis::DX12Sampler on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateSampler(const wis::SamplerDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplDX12Device::CreateSampler, this, desc }; } /** * @brief Creates a shader resource object. @@ -252,9 +378,39 @@ class DX12Device : public wis::ImplDX12Device * @param desc The description of the shader resource to create. * @return wis::DX12ShaderResource on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateShaderResource(wis::DX12TextureView texture, wis::ShaderResourceDesc desc) const noexcept + [[nodiscard]] inline wis::DX12ShaderResource CreateShaderResource(wis::Result& result, wis::DX12TextureView texture, const wis::ShaderResourceDesc& desc) const noexcept + { + return wis::ImplDX12Device::CreateShaderResource(result, std::move(texture), desc); + } + /** + * @brief Creates a shader resource object. + * @param texture The texture view to create the shader resource with. + * @param desc The description of the shader resource to create. + * @return wis::DX12ShaderResource on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateShaderResource(wis::DX12TextureView texture, const wis::ShaderResourceDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplDX12Device::CreateShaderResource, this, std::move(texture), desc }; + } + /** + * @brief Creates a descriptor storage object with specified number of bindings to allocate. + * Switching between several DescriptorStorage is slow, consider allocating one big set and copy descriptors to it. + * @param desc The description of the descriptor storage to create. + * @return wis::DX12DescriptorStorage on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12DescriptorStorage CreateDescriptorStorage(wis::Result& result, const wis::DescriptorStorageDesc& desc) const noexcept + { + return wis::ImplDX12Device::CreateDescriptorStorage(result, desc); + } + /** + * @brief Creates a descriptor storage object with specified number of bindings to allocate. + * Switching between several DescriptorStorage is slow, consider allocating one big set and copy descriptors to it. + * @param desc The description of the descriptor storage to create. + * @return wis::DX12DescriptorStorage on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateDescriptorStorage(const wis::DescriptorStorageDesc& desc) const noexcept { - return wis::ImplDX12Device::CreateShaderResource(std::move(texture), desc); + return wis::ResultValue{ &wis::ImplDX12Device::CreateDescriptorStorage, this, desc }; } /** * @brief Queries if the device supports the feature. @@ -268,8 +424,8 @@ class DX12Device : public wis::ImplDX12Device }; #pragma endregion DX12Device -[[nodiscard]] WIS_INLINE wis::ResultValue -ImplDX12CreateDevice(wis::DX12Adapter adapter, wis::DX12DeviceExtension** extensions, uint32_t ext_count, bool force) noexcept; +[[nodiscard]] WIS_INLINE wis::DX12Device +ImplDX12CreateDevice(wis::Result& result, wis::DX12Adapter adapter, wis::DX12DeviceExtension** extensions, uint32_t ext_count, bool force) noexcept; } // namespace wis #ifndef WISDOM_BUILD_BINARIES diff --git a/wisdom/include/wisdom/dx12/dx12_device_ext.h b/wisdom/include/wisdom/dx12/dx12_device_ext.h index dc5e65a0..4f86e74e 100644 --- a/wisdom/include/wisdom/dx12/dx12_device_ext.h +++ b/wisdom/include/wisdom/dx12/dx12_device_ext.h @@ -1,7 +1,7 @@ #ifndef WIS_DX12_DEVICE_EXT_H #define WIS_DX12_DEVICE_EXT_H -#include +#include namespace wis { class DX12Device; diff --git a/wisdom/include/wisdom/dx12/dx12_factory.h b/wisdom/include/wisdom/dx12/dx12_factory.h index 9400c580..8b393a86 100644 --- a/wisdom/include/wisdom/dx12/dx12_factory.h +++ b/wisdom/include/wisdom/dx12/dx12_factory.h @@ -17,16 +17,15 @@ struct Internal { /// @brief Main Factory class class ImplDX12Factory : public QueryInternal { - friend wis::ResultValue - ImplDX12CreateFactory(bool enable_debug, DX12FactoryExtension** extensions, size_t extension_count) noexcept; + // friend wis::ResultValue + // ImplDX12CreateFactory(bool enable_debug, DX12FactoryExtension** extensions, size_t extension_count) noexcept; + friend wis::DX12Factory + ImplDX12CreateFactory(bool enable_debug, DX12FactoryExtension** extensions, size_t extension_count, wis::Result& res) noexcept; public: ImplDX12Factory() noexcept = default; - WIS_INLINE explicit ImplDX12Factory(wis::com_ptr factory) noexcept; ImplDX12Factory(ImplDX12Factory&& other) noexcept = default; ImplDX12Factory& operator=(ImplDX12Factory&& other) noexcept = default; - ImplDX12Factory(const ImplDX12Factory&) = delete; - ImplDX12Factory& operator=(const ImplDX12Factory&) = delete; operator bool() const noexcept { @@ -38,18 +37,9 @@ class ImplDX12Factory : public QueryInternal } public: - [[nodiscard]] WIS_INLINE wis::ResultValue - GetAdapter(uint32_t index, + [[nodiscard]] WIS_INLINE wis::DX12Adapter + GetAdapter(wis::Result& result, uint32_t index, AdapterPreference preference = AdapterPreference::Performance) const noexcept; - -private: - WIS_INLINE wis::com_with_result GetAdapterByGPUPreference( - uint32_t index, DXGI_GPU_PREFERENCE preference = DXGI_GPU_PREFERENCE::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE) const noexcept; - - WIS_INLINE wis::com_with_result GetAdapter1(uint32_t index) const noexcept; - -private: - static inline bool has_preference = true; }; #pragma region DX12Factory @@ -63,6 +53,17 @@ class DX12Factory : public wis::ImplDX12Factory using wis::ImplDX12Factory::ImplDX12Factory; public: + /** + * @brief Creates the wis::DX12Adapter for the factory with provided index. + * @param index The index of the adapter to get. + * @param preference The preference of the adapter to get. + * Default is wis::AdapterPreference::Performance. + * @return wis::DX12Adapter on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::DX12Adapter GetAdapter(wis::Result& result, uint32_t index, wis::AdapterPreference preference = wis::AdapterPreference::Performance) const noexcept + { + return wis::ImplDX12Factory::GetAdapter(result, index, preference); + } /** * @brief Creates the wis::DX12Adapter for the factory with provided index. * @param index The index of the adapter to get. @@ -72,14 +73,13 @@ class DX12Factory : public wis::ImplDX12Factory * */ [[nodiscard]] inline wis::ResultValue GetAdapter(uint32_t index, wis::AdapterPreference preference = wis::AdapterPreference::Performance) const noexcept { - return wis::ImplDX12Factory::GetAdapter(index, preference); + return wis::ResultValue{ &wis::ImplDX12Factory::GetAdapter, this, index, preference }; } }; #pragma endregion DX12Factory -[[nodiscard]] WIS_INLINE wis::ResultValue -ImplDX12CreateFactory(bool enable_debug, DX12FactoryExtension** extensions, size_t extension_count) noexcept; - +[[nodiscard]] WIS_INLINE wis::DX12Factory +ImplDX12CreateFactory(wis::Result& result, bool enable_debug, DX12FactoryExtension** extensions, size_t extension_count) noexcept; } // namespace wis #ifndef WISDOM_BUILD_BINARIES diff --git a/wisdom/include/wisdom/dx12/dx12_factory_ext.h b/wisdom/include/wisdom/dx12/dx12_factory_ext.h index ece69ba3..ca2f9c03 100644 --- a/wisdom/include/wisdom/dx12/dx12_factory_ext.h +++ b/wisdom/include/wisdom/dx12/dx12_factory_ext.h @@ -1,6 +1,6 @@ #ifndef WIS_DX12_FACTORY_EXT_H #define WIS_DX12_FACTORY_EXT_H -#include +#include namespace wis { class DX12Factory; diff --git a/wisdom/include/wisdom/dx12/dx12_fence.h b/wisdom/include/wisdom/dx12/dx12_fence.h index cafe94ce..a06a307e 100644 --- a/wisdom/include/wisdom/dx12/dx12_fence.h +++ b/wisdom/include/wisdom/dx12/dx12_fence.h @@ -13,15 +13,13 @@ class DX12Fence; template<> struct Internal { wis::com_ptr fence; - wis::unique_event fence_event; + wis::unique_event fence_event = CreateEventW(nullptr, false, false, nullptr); }; class ImplDX12Fence : public QueryInternal { public: - ImplDX12Fence() = default; - explicit ImplDX12Fence(wis::com_ptr xfence) noexcept - : QueryInternal(std::move(xfence), CreateEventW(nullptr, false, false, nullptr)) { } + ImplDX12Fence() noexcept = default; operator DX12FenceView() const noexcept { diff --git a/wisdom/include/wisdom/dx12/dx12_info.h b/wisdom/include/wisdom/dx12/dx12_info.h index 98d9f05d..dd13b11b 100644 --- a/wisdom/include/wisdom/dx12/dx12_info.h +++ b/wisdom/include/wisdom/dx12/dx12_info.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include @@ -58,15 +58,17 @@ struct DX12InfoToken { } DX12InfoToken& operator=(DX12InfoToken&& other) noexcept { - if (bound) + if (bound) { Release(); + } bound = std::exchange(other.bound, false); return *this; } ~DX12InfoToken() { - if (bound) + if (bound) { Release(); + } } void Acquire() noexcept diff --git a/wisdom/include/wisdom/dx12/dx12_memory.h b/wisdom/include/wisdom/dx12/dx12_memory.h index e4eb5e11..5777bb4f 100644 --- a/wisdom/include/wisdom/dx12/dx12_memory.h +++ b/wisdom/include/wisdom/dx12/dx12_memory.h @@ -12,20 +12,12 @@ template<> struct Internal { wis::com_ptr allocator; wis::com_ptr allocation; - - Internal() noexcept = default; - Internal(wis::com_ptr allocator, wis::com_ptr allocation) noexcept - : allocator(std::move(allocator)), allocation(std::move(allocation)) { } }; class ImplDX12Memory : public QueryInternal { public: ImplDX12Memory() noexcept = default; - explicit ImplDX12Memory(wis::com_ptr allocator, wis::com_ptr allocation) noexcept - : QueryInternal(std::move(allocator), std::move(allocation)) - { - } operator bool() const noexcept { return bool(allocation); @@ -48,8 +40,9 @@ class ImplDX12Memory : public QueryInternal public: [[nodiscard]] uint64_t GetBlockOffset() const noexcept { - if (!allocation) + if (!allocation) { return 0; + } return allocation->GetOffset(); } diff --git a/wisdom/include/wisdom/dx12/dx12_pipeline_state.h b/wisdom/include/wisdom/dx12/dx12_pipeline_state.h index 870a39d6..cf2cd4b2 100644 --- a/wisdom/include/wisdom/dx12/dx12_pipeline_state.h +++ b/wisdom/include/wisdom/dx12/dx12_pipeline_state.h @@ -17,9 +17,6 @@ class DX12PipelineState : public QueryInternal { public: DX12PipelineState() = default; - explicit DX12PipelineState(wis::com_ptr xpipeline) noexcept - : QueryInternal(std::move(xpipeline)) { } - operator DX12PipelineView() const noexcept { return pipeline.get(); diff --git a/wisdom/include/wisdom/dx12/dx12_resource.h b/wisdom/include/wisdom/dx12/dx12_resource.h index cea64a2d..949d2af0 100644 --- a/wisdom/include/wisdom/dx12/dx12_resource.h +++ b/wisdom/include/wisdom/dx12/dx12_resource.h @@ -17,13 +17,6 @@ class ImplDX12Buffer : public QueryInternal { public: ImplDX12Buffer() noexcept = default; - explicit ImplDX12Buffer(wis::com_ptr rc, wis::com_ptr al, wis::com_ptr allocator) noexcept - : QueryInternal(DX12Memory{ - std::move(allocator), std::move(al) }, - std::move(rc)) - { - } - operator DX12BufferView() const noexcept { return resource.get(); @@ -67,9 +60,6 @@ class DX12RenderTarget : public QueryInternal { public: DX12RenderTarget() = default; - explicit DX12RenderTarget(wis::com_ptr desc, D3D12_CPU_DESCRIPTOR_HANDLE handle) noexcept - : QueryInternal(std::move(desc), handle) { } - operator bool() const noexcept { return bool(heap); @@ -93,9 +83,6 @@ class DX12Sampler : public QueryInternal { public: DX12Sampler() noexcept = default; - explicit DX12Sampler(wis::com_ptr heap) noexcept - : QueryInternal(std::move(heap)) { } - operator bool() const noexcept { return bool(heap); @@ -119,9 +106,6 @@ class DX12ShaderResource : public QueryInternal { public: DX12ShaderResource() noexcept = default; - explicit DX12ShaderResource(wis::com_ptr heap) noexcept - : QueryInternal(std::move(heap)) { } - operator bool() const noexcept { return bool(heap); diff --git a/wisdom/include/wisdom/dx12/dx12_root_signature.h b/wisdom/include/wisdom/dx12/dx12_root_signature.h index cf09c945..78be73a6 100644 --- a/wisdom/include/wisdom/dx12/dx12_root_signature.h +++ b/wisdom/include/wisdom/dx12/dx12_root_signature.h @@ -16,15 +16,8 @@ struct Internal { class DX12RootSignature : public QueryInternal { -public: - static constexpr inline auto root_const_register = 16; - public: DX12RootSignature() = default; - explicit DX12RootSignature(wis::com_ptr xroot, std::array stage_map, uint32_t push_constant_count, uint32_t push_descriptor_count) noexcept - : QueryInternal(std::move(xroot), stage_map, push_constant_count, push_descriptor_count) - { - } operator DX12RootSignatureView() const noexcept { return { root.get(), stage_map, push_constant_count, push_descriptor_count }; diff --git a/wisdom/include/wisdom/dx12/dx12_shader.h b/wisdom/include/wisdom/dx12/dx12_shader.h index 01721e39..eb841e7e 100644 --- a/wisdom/include/wisdom/dx12/dx12_shader.h +++ b/wisdom/include/wisdom/dx12/dx12_shader.h @@ -17,10 +17,6 @@ class DX12Shader : public QueryInternal { public: DX12Shader() = default; - explicit DX12Shader(std::unique_ptr bytecode, size_t size) noexcept - : QueryInternal(std::move(bytecode), size) - { - } operator DX12ShaderView() const noexcept { return DX12ShaderView((void*)(bytecode.get()), uint32_t(size)); diff --git a/wisdom/include/wisdom/dx12/dx12_swapchain.h b/wisdom/include/wisdom/dx12/dx12_swapchain.h index 23462e3b..cb7100bd 100644 --- a/wisdom/include/wisdom/dx12/dx12_swapchain.h +++ b/wisdom/include/wisdom/dx12/dx12_swapchain.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include #include #include @@ -33,10 +33,6 @@ class ImplDX12SwapChain : public QueryInternal { public: ImplDX12SwapChain() noexcept = default; - explicit ImplDX12SwapChain(detail::DX12SwapChainCreateInfo&& swap_i) noexcept - : QueryInternal(std::move(swap_i)) - { - } operator bool() const noexcept { return bool(chain); diff --git a/wisdom/include/wisdom/dx12/dx12_unique_event.h b/wisdom/include/wisdom/dx12/dx12_unique_event.h index 0d7b1199..fc4b3b22 100644 --- a/wisdom/include/wisdom/dx12/dx12_unique_event.h +++ b/wisdom/include/wisdom/dx12/dx12_unique_event.h @@ -1,6 +1,6 @@ #ifndef WIS_DX12_UNIQUE_EVENT_H #define WIS_DX12_UNIQUE_EVENT_H -#include +#include #include namespace wis { @@ -18,8 +18,9 @@ struct unique_event { } ~unique_event() noexcept { - if (hevent) + if (hevent) { CloseHandle(hevent); + } } auto get() const noexcept { @@ -32,10 +33,12 @@ struct unique_event { wis::Status wait(uint32_t wait_ms) const noexcept { auto st = WaitForSingleObject(hevent, wait_ms); - if (st == WAIT_OBJECT_0) + if (st == WAIT_OBJECT_0) { return wis::Status::Ok; - if (st == WAIT_TIMEOUT) + } + if (st == WAIT_TIMEOUT) { return wis::Status::Timeout; + } return wis::Status::Error; } diff --git a/wisdom/include/wisdom/dx12/dx12_views.h b/wisdom/include/wisdom/dx12/dx12_views.h index e52eed4c..892334ef 100644 --- a/wisdom/include/wisdom/dx12/dx12_views.h +++ b/wisdom/include/wisdom/dx12/dx12_views.h @@ -1,6 +1,6 @@ #ifndef WIS_DX12_VIEWS_H #define WIS_DX12_VIEWS_H -#include +#include #include #include #include diff --git a/wisdom/include/wisdom/dx12/impl/dx12_allocator.cpp b/wisdom/include/wisdom/dx12/impl/dx12_allocator.cpp index d2e04b20..d3884a80 100644 --- a/wisdom/include/wisdom/dx12/impl/dx12_allocator.cpp +++ b/wisdom/include/wisdom/dx12/impl/dx12_allocator.cpp @@ -7,9 +7,10 @@ #include #include #include +#include -wis::ResultValue -wis::ImplDX12ResourceAllocator::CreateBuffer(uint64_t size, wis::BufferUsage usage, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept +wis::DX12Buffer +wis::ImplDX12ResourceAllocator::CreateBuffer(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept { D3D12_RESOURCE_DESC1 buffer_desc; DX12FillBufferDesc(size, usage, buffer_desc); @@ -19,10 +20,10 @@ wis::ImplDX12ResourceAllocator::CreateBuffer(uint64_t size, wis::BufferUsage usa .HeapType = convert_dx(memory), }; - return DX12CreateResource(all_desc, buffer_desc, D3D12_RESOURCE_STATE_COMMON); + return DX12CreateResource(result, all_desc, buffer_desc, D3D12_RESOURCE_STATE_COMMON); } -wis::ResultValue -wis::ImplDX12ResourceAllocator::CreateTexture(const wis::TextureDesc& desc, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept +wis::DX12Texture +wis::ImplDX12ResourceAllocator::CreateTexture(wis::Result& result, const wis::TextureDesc& desc, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept { D3D12_RESOURCE_DESC1 tex_desc; DX12FillTextureDesc(desc, tex_desc); @@ -32,7 +33,7 @@ wis::ImplDX12ResourceAllocator::CreateTexture(const wis::TextureDesc& desc, wis: .HeapType = convert_dx(memory), }; - return DX12CreateResource(all_desc, tex_desc, D3D12_RESOURCE_STATE_COMMON); + return DX12CreateResource(result, all_desc, tex_desc, D3D12_RESOURCE_STATE_COMMON); } wis::AllocationInfo @@ -64,23 +65,28 @@ wis::ImplDX12ResourceAllocator::GetBufferAllocationInfo(uint64_t size, BufferUsa }; } -wis::ResultValue -wis::ImplDX12ResourceAllocator::AllocateTextureMemory(uint64_t size, wis::TextureUsage usage, +wis::DX12Memory +wis::ImplDX12ResourceAllocator::AllocateTextureMemory(wis::Result& result, uint64_t size, wis::TextureUsage usage, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept { + DX12Memory out_memory; + auto& internal = out_memory.GetMutableInternal(); D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_DENY_BUFFERS; if ((mem_flags & MemoryFlags::Exportable)) { - if (memory != MemoryType::Default) - return wis::make_result(E_INVALIDARG); + if (memory != MemoryType::Default) { + result = wis::make_result(E_INVALIDARG); + return out_memory; + } flags |= D3D12_HEAP_FLAG_SHARED; } - if (!(usage & (wis::TextureUsage::RenderTarget | wis::TextureUsage::DepthStencil))) + if (!(usage & (wis::TextureUsage::RenderTarget | wis::TextureUsage::DepthStencil))) { flags |= D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES; - else if (!(usage & ~(wis::TextureUsage::RenderTarget | wis::TextureUsage::DepthStencil))) + } else if (!(usage & ~(wis::TextureUsage::RenderTarget | wis::TextureUsage::DepthStencil))) { flags |= D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES; + } auto info = GetTextureAllocationInfo({ .format = wis::DataFormat::RGBA8Unorm, .size = { 1, 1, 1 }, .mip_levels = 1, .usage = usage }); @@ -94,29 +100,31 @@ wis::ImplDX12ResourceAllocator::AllocateTextureMemory(uint64_t size, wis::Textur .SizeInBytes = size, .Alignment = info.alignment_bytes, }; + auto hr = allocator->AllocateMemory(&all_desc, &alloc_info, internal.allocation.put()); - wis::com_ptr allocation; - auto hr = allocator->AllocateMemory(&all_desc, &alloc_info, allocation.put()); - - if (!wis::succeeded(hr)) - return wis::make_result(hr); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } - return DX12Memory{ - allocator, - std::move(allocation) - }; + internal.allocator = allocator; // Copy allocator to memory + return out_memory; } -wis::ResultValue -wis::ImplDX12ResourceAllocator::AllocateBufferMemory(uint64_t size, wis::BufferUsage usage, +wis::DX12Memory +wis::ImplDX12ResourceAllocator::AllocateBufferMemory(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept { + DX12Memory out_memory; + auto& internal = out_memory.GetMutableInternal(); + D3D12_HEAP_FLAGS flags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; if ((mem_flags & MemoryFlags::Exportable)) { - if (memory != MemoryType::Default) - return wis::make_result(E_INVALIDARG); + if (memory != MemoryType::Default) { + result = wis::make_result(E_INVALIDARG); + return out_memory; + } flags |= D3D12_HEAP_FLAG_SHARED; } @@ -132,66 +140,71 @@ wis::ImplDX12ResourceAllocator::AllocateBufferMemory(uint64_t size, wis::BufferU .Alignment = info.alignment_bytes, }; - wis::com_ptr allocation; - auto hr = allocator->AllocateMemory(&all_desc, &alloc_info, allocation.put()); - - if (!wis::succeeded(hr)) - return wis::make_result(hr); + auto hr = allocator->AllocateMemory(&all_desc, &alloc_info, internal.allocation.put()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } - return DX12Memory{ - allocator, - std::move(allocation), - }; + internal.allocator = allocator; // Copy allocator to memory + return out_memory; } -wis::ResultValue -wis::ImplDX12ResourceAllocator::PlaceBuffer(DX12MemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept +wis::DX12Buffer +wis::ImplDX12ResourceAllocator::PlaceBuffer(wis::Result& result, DX12MemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept { + wis::DX12Buffer buffer; + auto& internal = buffer.GetMutableInternal(); + auto* alloc = std::get<1>(memory); D3D12_RESOURCE_DESC1 buffer_desc; DX12FillBufferDesc(size, usage, buffer_desc); - wis::com_ptr rc; auto hr = allocator->CreateAliasingResource1(alloc, memory_offset, &buffer_desc, - D3D12_RESOURCE_STATE_COMMON, nullptr, rc.iid(), rc.put_void()); - - if (!wis::succeeded(hr)) - return wis::make_result(hr); + D3D12_RESOURCE_STATE_COMMON, nullptr, internal.resource.iid(), internal.resource.put_void()); - return DX12Buffer{ std::move(rc), nullptr, nullptr }; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } + return buffer; } -wis::ResultValue -wis::ImplDX12ResourceAllocator::PlaceTexture(DX12MemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept +wis::DX12Texture +wis::ImplDX12ResourceAllocator::PlaceTexture(wis::Result& result, DX12MemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept { + wis::DX12Texture texture; + auto& internal = texture.GetMutableInternal(); + auto* alloc = std::get<1>(memory); D3D12_RESOURCE_DESC1 tex_desc; DX12FillTextureDesc(desc, tex_desc); - wis::com_ptr rc; auto hr = allocator->CreateAliasingResource1(alloc, memory_offset, &tex_desc, - D3D12_RESOURCE_STATE_COMMON, nullptr, rc.iid(), rc.put_void()); + D3D12_RESOURCE_STATE_COMMON, nullptr, internal.resource.iid(), internal.resource.put_void()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); - - return DX12Buffer{ std::move(rc), nullptr, nullptr }; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } + return texture; } -wis::ResultValue -wis::ImplDX12ResourceAllocator::DX12CreateResource(const D3D12MA::ALLOCATION_DESC& all_desc, const D3D12_RESOURCE_DESC1& res_desc, D3D12_RESOURCE_STATES state) const noexcept +wis::DX12Buffer +wis::ImplDX12ResourceAllocator::DX12CreateResource(wis::Result& result, const D3D12MA::ALLOCATION_DESC& all_desc, const D3D12_RESOURCE_DESC1& res_desc, D3D12_RESOURCE_STATES state) const noexcept { - wis::com_ptr rc; - wis::com_ptr al; + wis::DX12Buffer buffer; + auto& internal = buffer.GetMutableInternal(); + auto& memory_internal = internal.memory.GetMutableInternal(); HRESULT hr = allocator->CreateResource2(&all_desc, &res_desc, state, nullptr, - al.put(), __uuidof(*rc), rc.put_void()); + memory_internal.allocation.put(), __uuidof(*internal.resource), internal.resource.put_void()); + + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } - if (!wis::succeeded(hr)) - return wis::make_result(hr); + memory_internal.allocator = allocator; // Copy allocator to memory - return DX12Buffer{ std::move(rc), std::move(al), allocator }; + return buffer; } void wis::ImplDX12ResourceAllocator::DX12FillBufferDesc(uint64_t size, BufferUsage flags, D3D12_RESOURCE_DESC1& info) noexcept diff --git a/wisdom/include/wisdom/dx12/impl/dx12_device.cpp b/wisdom/include/wisdom/dx12/impl/dx12_device.cpp index fff299ad..95548823 100644 --- a/wisdom/include/wisdom/dx12/impl/dx12_device.cpp +++ b/wisdom/include/wisdom/dx12/impl/dx12_device.cpp @@ -10,31 +10,29 @@ #include #include -wis::ResultValue -wis::ImplDX12CreateDevice(wis::DX12Adapter adapter, wis::DX12DeviceExtension** extensions, uint32_t ext_count, bool force) noexcept +wis::DX12Device +wis::ImplDX12CreateDevice(wis::Result& result, wis::DX12Adapter adapter, wis::DX12DeviceExtension** extensions, uint32_t ext_count, bool force) noexcept { - auto in_adapter = adapter.GetInternal().adapter.get(); - - wis::com_ptr in_factory; - in_adapter->GetParent(__uuidof(*in_factory), in_factory.put_void()); - - wis::com_ptr device; - - HRESULT hr = D3D12CreateDevice(in_adapter, D3D_FEATURE_LEVEL_11_0, - __uuidof(ID3D12Device9), device.put_void()); - - if (!wis::succeeded(hr)) - return wis::make_result(hr); - - auto xdevice = wis::DX12Device(std::move(device), wis::com_ptr(in_adapter), std::move(in_factory)); - - if (!xdevice.QueryFeatureSupport(wis::DeviceFeature::EnchancedBarriers) && !force) - return wis::make_result(E_FAIL); + DX12Device out_device; + auto& internal = out_device.GetMutableInternal(); + internal.adapter = adapter.GetInternal().adapter; // Keep adapter alive + internal.adapter->GetParent(internal.factory.iid(), internal.factory.put_void()); + HRESULT hr = D3D12CreateDevice(internal.adapter.get(), D3D_FEATURE_LEVEL_11_0, + __uuidof(ID3D12Device9), internal.device.put_void()); + + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_device; + } + if (!out_device.QueryFeatureSupport(wis::DeviceFeature::EnchancedBarriers) && !force) { + result = wis::make_result(E_FAIL); + return out_device; + } for (uint32_t i = 0; i < ext_count; i++) { - extensions[i]->Init(xdevice); + extensions[i]->Init(out_device); } - return std::move(xdevice); + return out_device; } wis::Result wis::ImplDX12Device::WaitForMultipleFences(const DX12FenceView* fences, @@ -47,9 +45,10 @@ wis::Result wis::ImplDX12Device::WaitForMultipleFences(const DX12FenceView* fenc if (!succeeded(hr = device->SetEventOnMultipleFenceCompletion( reinterpret_cast(fences), values, count, - static_cast(wait_all), e.get()))) + static_cast(wait_all), e.get()))) { return wis::make_result(hr); + } auto st = e.wait(uint32_t(timeout)); return st == wis::Status::Timeout ? wis::Result{ st, "Wait timed out" } @@ -57,54 +56,61 @@ wis::Result wis::ImplDX12Device::WaitForMultipleFences(const DX12FenceView* fenc : wis::make_result(E_FAIL); } -wis::ResultValue -wis::ImplDX12Device::CreateFence(uint64_t initial_value, wis::FenceFlags flags) const noexcept +wis::DX12Fence +wis::ImplDX12Device::CreateFence(wis::Result& result, uint64_t initial_value, wis::FenceFlags flags) const noexcept { - wis::com_ptr fence; - HRESULT hr = device->CreateFence(initial_value, convert_dx(flags), - __uuidof(*fence), fence.put_void()); + wis::DX12Fence out_fence; + auto& internal = out_fence.GetMutableInternal(); - if (!wis::succeeded(hr)) - return wis::make_result(hr); + HRESULT hr = device->CreateFence(initial_value, convert_dx(flags), + internal.fence.iid(), internal.fence.put_void()); - return DX12Fence{ std::move(fence) }; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } + return out_fence; } -wis::ResultValue -wis::ImplDX12Device::CreateCommandQueue(wis::QueueType type) const noexcept +wis::DX12CommandQueue +wis::ImplDX12Device::CreateCommandQueue(wis::Result& result, wis::QueueType type) const noexcept { - wis::com_ptr queue; + DX12CommandQueue out_queue; + auto& internal = out_queue.GetMutableInternal(); + D3D12_COMMAND_QUEUE_DESC desc{ .Type = D3D12_COMMAND_LIST_TYPE(type), .Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL, }; - HRESULT hr = device->CreateCommandQueue(&desc, __uuidof(*queue), queue.put_void()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); + HRESULT hr = device->CreateCommandQueue(&desc, internal.queue.iid(), internal.queue.put_void()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } - return DX12CommandQueue{ std::move(queue) }; + return out_queue; } -wis::ResultValue -wis::ImplDX12Device::CreateCommandList(wis::QueueType type) const noexcept +wis::DX12CommandList +wis::ImplDX12Device::CreateCommandList(wis::Result& result, wis::QueueType type) const noexcept { - D3D12_COMMAND_LIST_TYPE clty = D3D12_COMMAND_LIST_TYPE(type); - wis::com_ptr allocator; - wis::com_ptr command_list; + DX12CommandList out_list; + auto& internal = out_list.GetMutableInternal(); - HRESULT hr = device->CreateCommandAllocator(clty, __uuidof(*allocator), allocator.put_void()); - - if (!wis::succeeded(hr)) - return wis::make_result(hr); + D3D12_COMMAND_LIST_TYPE clty = D3D12_COMMAND_LIST_TYPE(type); + HRESULT hr = device->CreateCommandAllocator(clty, internal.allocator.iid(), internal.allocator.put_void()); - hr = device->CreateCommandList(0, clty, allocator.get(), nullptr, - __uuidof(*command_list), command_list.put_void()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_list; + } - if (!wis::succeeded(hr)) - return wis::make_result(hr); + hr = device->CreateCommandList(0, clty, internal.allocator.get(), nullptr, + internal.list.iid(), internal.list.put_void()); - return DX12CommandList{ std::move(allocator), std::move(command_list) }; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } + return out_list; } namespace wis::detail { @@ -120,48 +126,51 @@ inline void DX12FillShaderStage(wis::detail::memory_pool<1024>& pipeline_stream, } } // namespace wis::detail -wis::ResultValue -wis::ImplDX12Device::CreateGraphicsPipeline(const wis::DX12GraphicsPipelineDesc* desc) const noexcept +wis::DX12PipelineState +wis::ImplDX12Device::CreateGraphicsPipeline(wis::Result& result, const wis::DX12GraphicsPipelineDesc& desc) const noexcept { - wis::com_ptr state; + DX12PipelineState out_state; + auto& internal = out_state.GetMutableInternal(); + //--Shader stages wis::detail::memory_pool pipeline_stream; wis::detail::DX12FillShaderStage(pipeline_stream, - desc->shaders.vertex); + desc.shaders.vertex); wis::detail::DX12FillShaderStage(pipeline_stream, - desc->shaders.pixel); + desc.shaders.pixel); wis::detail::DX12FillShaderStage(pipeline_stream, - desc->shaders.geometry); + desc.shaders.geometry); wis::detail::DX12FillShaderStage(pipeline_stream, - desc->shaders.hull); + desc.shaders.hull); wis::detail::DX12FillShaderStage(pipeline_stream, - desc->shaders.domain); + desc.shaders.domain); //--Topology pipeline_stream.allocate() = - convert_dx(desc->topology_type); + convert_dx(desc.topology_type); //--Root signature pipeline_stream.allocate() = - std::get<0>(desc->root_signature); + std::get<0>(desc.root_signature); //--Input layout wis::detail::limited_allocator ia_stage{ - desc->input_layout.attribute_count + desc.input_layout.attribute_count }; auto slots = - std::span{ desc->input_layout.slots, desc->input_layout.slots + desc->input_layout.slot_count }; - auto attrs = std::span{ desc->input_layout.attributes, - desc->input_layout.attributes + desc->input_layout.attribute_count }; + std::span{ desc.input_layout.slots, desc.input_layout.slots + desc.input_layout.slot_count }; + auto attrs = std::span{ desc.input_layout.attributes, + desc.input_layout.attributes + desc.input_layout.attribute_count }; for (auto& i : attrs) { auto slot = std::find_if(slots.begin(), slots.end(), [&](auto& s) { return s.slot == i.input_slot; }); - if (slot == slots.end()) + if (slot == slots.end()) { continue; + } *ia_stage.allocate() = { .SemanticName = i.semantic_name, .SemanticIndex = i.semantic_index, @@ -177,33 +186,33 @@ wis::ImplDX12Device::CreateGraphicsPipeline(const wis::DX12GraphicsPipelineDesc* }; //--Rasterizer - if (desc->rasterizer) { - bool bias = desc->rasterizer->depth_bias_enable; + if (desc.rasterizer) { + bool bias = desc.rasterizer->depth_bias_enable; pipeline_stream.allocate() = CD3DX12_RASTERIZER_DESC2{ D3D12_RASTERIZER_DESC2{ - .FillMode = convert_dx(desc->rasterizer->fill_mode), - .CullMode = convert_dx(desc->rasterizer->cull_mode), - .FrontCounterClockwise = convert_dx(desc->rasterizer->front_face), - .DepthBias = bias ? desc->rasterizer->depth_bias : 0.0f, - .DepthBiasClamp = bias ? desc->rasterizer->depth_bias_clamp : 0.0f, - .SlopeScaledDepthBias = bias ? desc->rasterizer->depth_bias_slope_factor : 0.0f, - .DepthClipEnable = desc->rasterizer->depth_clip_enable, + .FillMode = convert_dx(desc.rasterizer->fill_mode), + .CullMode = convert_dx(desc.rasterizer->cull_mode), + .FrontCounterClockwise = convert_dx(desc.rasterizer->front_face), + .DepthBias = bias ? desc.rasterizer->depth_bias : 0.0f, + .DepthBiasClamp = bias ? desc.rasterizer->depth_bias_clamp : 0.0f, + .SlopeScaledDepthBias = bias ? desc.rasterizer->depth_bias_slope_factor : 0.0f, + .DepthClipEnable = desc.rasterizer->depth_clip_enable, } }; } //--Multisample - if (desc->sample) { + if (desc.sample) { pipeline_stream.allocate() = DXGI_SAMPLE_DESC{ - .Count = convert_dx(desc->sample->rate), + .Count = convert_dx(desc.sample->rate), .Quality = 0, }; pipeline_stream.allocate() = - desc->sample->sample_mask; + desc.sample->sample_mask; } //--Depth stencil - if (desc->depth_stencil) { - auto& ds = *desc->depth_stencil; + if (desc.depth_stencil) { + auto& ds = *desc.depth_stencil; pipeline_stream.allocate() = CD3DX12_DEPTH_STENCIL_DESC2{ D3D12_DEPTH_STENCIL_DESC2{ .DepthEnable = ds.depth_enable, @@ -234,21 +243,22 @@ wis::ImplDX12Device::CreateGraphicsPipeline(const wis::DX12GraphicsPipelineDesc* //--Render targets pipeline_stream.allocate( - convert_dx(desc->attachments.depth_attachment)); + convert_dx(desc.attachments.depth_attachment)); D3D12_RT_FORMAT_ARRAY rta{ .NumRenderTargets = uint32_t(std::min( - desc->attachments.attachments_count, wis::max_render_targets)) }; + desc.attachments.attachments_count, wis::max_render_targets)) }; for (size_t i = 0; i < rta.NumRenderTargets; i++) { - rta.RTFormats[i] = convert_dx(desc->attachments.attachment_formats[i]); + rta.RTFormats[i] = convert_dx(desc.attachments.attachment_formats[i]); } pipeline_stream.allocate() = rta; //--Multiview D3D12_VIEW_INSTANCE_LOCATION view_locs[8]{}; - if (desc->view_mask) { + if (desc.view_mask) { for (uint32_t i = 0u; i < 8u; i++) { - if (!(desc->view_mask & (1u << i))) + if (!(desc.view_mask & (1u << i))) { continue; + } view_locs[i] = D3D12_VIEW_INSTANCE_LOCATION{ .ViewportArrayIndex = 0, @@ -256,15 +266,15 @@ wis::ImplDX12Device::CreateGraphicsPipeline(const wis::DX12GraphicsPipelineDesc* }; } pipeline_stream.allocate() = CD3DX12_VIEW_INSTANCING_DESC{ - uint32_t(std::popcount(desc->view_mask)), + uint32_t(std::popcount(desc.view_mask)), view_locs, D3D12_VIEW_INSTANCING_FLAGS::D3D12_VIEW_INSTANCING_FLAG_ENABLE_VIEW_INSTANCE_MASKING }; } //--Blend - if (desc->blend) { - auto& blend = *desc->blend; + if (desc.blend) { + auto& blend = *desc.blend; D3D12_BLEND_DESC bdesc{ .AlphaToCoverageEnable = false, .IndependentBlendEnable = !blend.logic_op_enable, @@ -298,46 +308,58 @@ wis::ImplDX12Device::CreateGraphicsPipeline(const wis::DX12GraphicsPipelineDesc* .pPipelineStateSubobjectStream = pipeline_stream.data(), }; - HRESULT hr = device->CreatePipelineState(&psstream_desc, __uuidof(*state), state.put_void()); - - if (!wis::succeeded(hr)) - return wis::make_result(hr); + HRESULT hr = device->CreatePipelineState(&psstream_desc, internal.pipeline.iid(), internal.pipeline.put_void()); - return DX12PipelineState{ std::move(state) }; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } + return out_state; } -wis::ResultValue wis::ImplDX12Device::CreateShader(void* data, - size_t size) const noexcept +wis::DX12Shader +wis::ImplDX12Device::CreateShader(wis::Result& result, void* data, + size_t size) const noexcept { - auto x = wis::detail::make_unique_for_overwrite(size); + DX12Shader out_shader; + auto& internal = out_shader.GetMutableInternal(); - if (!x) - return wis::make_result(E_OUTOFMEMORY); + internal.bytecode = wis::detail::make_unique_for_overwrite(size); - std::copy_n(reinterpret_cast(data), size, x.get()); - return DX12Shader{ std::move(x), size }; + if (!internal.bytecode) { + result = wis::make_result(E_OUTOFMEMORY); + return out_shader; + } + internal.size = size; + std::copy_n(reinterpret_cast(data), size, internal.bytecode.get()); + return out_shader; } -wis::ResultValue -wis::ImplDX12Device::CreateAllocator() const noexcept +wis::DX12ResourceAllocator +wis::ImplDX12Device::CreateAllocator(wis::Result& result) const noexcept { + wis::DX12ResourceAllocator out_allocator; + auto& internal = out_allocator.GetMutableInternal(); + D3D12MA::ALLOCATOR_DESC desc{ .Flags = D3D12MA::ALLOCATOR_FLAGS::ALLOCATOR_FLAG_NONE, .pDevice = device.get(), .PreferredBlockSize = 0, .pAllocationCallbacks = nullptr, .pAdapter = adapter.get() }; - wis::com_ptr allocator; - HRESULT hr = D3D12MA::CreateAllocator(&desc, allocator.put()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); + HRESULT hr = D3D12MA::CreateAllocator(&desc, internal.allocator.put()); - return DX12ResourceAllocator{ std::move(allocator), device.get() }; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } + return out_allocator; } -wis::ResultValue -wis::ImplDX12Device::CreateRenderTarget(DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept +wis::DX12RenderTarget +wis::ImplDX12Device::CreateRenderTarget(wis::Result& result, DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept { + DX12RenderTarget out_target; + auto& internal = out_target.GetMutableInternal(); + D3D12_RENDER_TARGET_VIEW_DESC rtv_desc{ .Format = convert_dx(desc.format), .ViewDimension = D3D12_RTV_DIMENSION(desc.layout), @@ -389,14 +411,15 @@ wis::ImplDX12Device::CreateRenderTarget(DX12TextureView texture, wis::RenderTarg .NodeMask = 0u }; - wis::com_ptr heap; - auto hr = device->CreateDescriptorHeap(&heap_desc, __uuidof(*heap), heap.put_void()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); + auto hr = device->CreateDescriptorHeap(&heap_desc, internal.heap.iid(), internal.heap.put_void()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_target; + } - auto handle = heap->GetCPUDescriptorHandleForHeapStart(); - device->CreateRenderTargetView(std::get<0>(texture), &rtv_desc, handle); - return DX12RenderTarget{ std::move(heap), handle }; + internal.handle = internal.heap->GetCPUDescriptorHandleForHeapStart(); + device->CreateRenderTargetView(std::get<0>(texture), &rtv_desc, internal.handle); + return out_target; } namespace wis::detail { @@ -421,9 +444,12 @@ inline constexpr D3D12_DSV_DIMENSION to_dsv(wis::TextureLayout layout) noexcept } } // namespace wis::detail -wis::ResultValue -wis::ImplDX12Device::CreateDepthStencilTarget(DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept +wis::DX12RenderTarget +wis::ImplDX12Device::CreateDepthStencilTarget(wis::Result& result, DX12TextureView texture, wis::RenderTargetDesc desc) const noexcept { + DX12RenderTarget out_target; + auto& internal = out_target.GetMutableInternal(); + D3D12_DEPTH_STENCIL_VIEW_DESC rtv_desc{ .Format = convert_dx(desc.format), .ViewDimension = detail::to_dsv(desc.layout), @@ -467,38 +493,41 @@ wis::ImplDX12Device::CreateDepthStencilTarget(DX12TextureView texture, wis::Rend .NodeMask = 0u }; - wis::com_ptr heap; - auto hr = device->CreateDescriptorHeap(&heap_desc, __uuidof(*heap), heap.put_void()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); + auto hr = device->CreateDescriptorHeap(&heap_desc, internal.heap.iid(), internal.heap.put_void()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_target; + } - auto handle = heap->GetCPUDescriptorHandleForHeapStart(); - device->CreateDepthStencilView(std::get<0>(texture), &rtv_desc, handle); - return DX12RenderTarget{ std::move(heap), handle }; + internal.handle = internal.heap->GetCPUDescriptorHandleForHeapStart(); + device->CreateDepthStencilView(std::get<0>(texture), &rtv_desc, internal.handle); + return out_target; } -wis::ResultValue -wis::ImplDX12Device::CreateSampler(const wis::SamplerDesc* desc) const noexcept +wis::DX12Sampler +wis::ImplDX12Device::CreateSampler(wis::Result& result, const wis::SamplerDesc& desc) const noexcept { - auto min_filter = !desc->anisotropic ? convert_dx(desc->min_filter) : D3D12_FILTER_TYPE_LINEAR; - auto mag_filter = !desc->anisotropic ? convert_dx(desc->mag_filter) : D3D12_FILTER_TYPE_LINEAR; - auto basic_filter = D3D12_ENCODE_BASIC_FILTER(min_filter, mag_filter, convert_dx(desc->mip_filter), D3D12_FILTER_REDUCTION_TYPE::D3D12_FILTER_REDUCTION_TYPE_STANDARD); - auto filter = D3D12_FILTER(desc->anisotropic * D3D12_ANISOTROPIC_FILTERING_BIT | basic_filter); + DX12Sampler out_sampler; + auto& internal = out_sampler.GetMutableInternal(); + + auto min_filter = !desc.anisotropic ? convert_dx(desc.min_filter) : D3D12_FILTER_TYPE_LINEAR; + auto mag_filter = !desc.anisotropic ? convert_dx(desc.mag_filter) : D3D12_FILTER_TYPE_LINEAR; + auto basic_filter = D3D12_ENCODE_BASIC_FILTER(min_filter, mag_filter, convert_dx(desc.mip_filter), D3D12_FILTER_REDUCTION_TYPE::D3D12_FILTER_REDUCTION_TYPE_STANDARD); + auto filter = D3D12_FILTER(desc.anisotropic * D3D12_ANISOTROPIC_FILTERING_BIT | basic_filter); D3D12_SAMPLER_DESC sampler_desc{ .Filter = filter, - .AddressU = convert_dx(desc->address_u), - .AddressV = convert_dx(desc->address_v), - .AddressW = convert_dx(desc->address_w), - .MipLODBias = desc->mip_lod_bias, - .MaxAnisotropy = desc->anisotropic ? std::min(uint32_t(D3D12_MAX_MAXANISOTROPY), desc->max_anisotropy) : 0, - .ComparisonFunc = convert_dx(desc->comparison_op), - .BorderColor = { desc->border_color[0], desc->border_color[1], desc->border_color[2], desc->border_color[3] }, - .MinLOD = desc->min_lod, - .MaxLOD = desc->max_lod, + .AddressU = convert_dx(desc.address_u), + .AddressV = convert_dx(desc.address_v), + .AddressW = convert_dx(desc.address_w), + .MipLODBias = desc.mip_lod_bias, + .MaxAnisotropy = desc.anisotropic ? std::min(uint32_t(D3D12_MAX_MAXANISOTROPY), desc.max_anisotropy) : 0, + .ComparisonFunc = convert_dx(desc.comparison_op), + .BorderColor = { desc.border_color[0], desc.border_color[1], desc.border_color[2], desc.border_color[3] }, + .MinLOD = desc.min_lod, + .MaxLOD = desc.max_lod, }; - wis::com_ptr heap; D3D12_DESCRIPTOR_HEAP_DESC heap_desc{ .Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, .NumDescriptors = 1, @@ -506,14 +535,17 @@ wis::ImplDX12Device::CreateSampler(const wis::SamplerDesc* desc) const noexcept }; auto x = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); - device->CreateDescriptorHeap(&heap_desc, heap.iid(), heap.put_void()); - device->CreateSampler(&sampler_desc, heap->GetCPUDescriptorHandleForHeapStart()); - return wis::DX12Sampler{ std::move(heap) }; + device->CreateDescriptorHeap(&heap_desc, internal.heap.iid(), internal.heap.put_void()); + device->CreateSampler(&sampler_desc, internal.heap->GetCPUDescriptorHandleForHeapStart()); + return out_sampler; } -wis::ResultValue -wis::ImplDX12Device::CreateShaderResource(DX12TextureView texture, wis::ShaderResourceDesc desc) const noexcept +wis::DX12ShaderResource +wis::ImplDX12Device::CreateShaderResource(wis::Result& result, DX12TextureView texture, wis::ShaderResourceDesc desc) const noexcept { + DX12ShaderResource out_resource; + auto& internal = out_resource.GetMutableInternal(); + D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc{ .Format = convert_dx(desc.format), .ViewDimension = convert_dx(desc.view_type), @@ -594,7 +626,6 @@ wis::ImplDX12Device::CreateShaderResource(DX12TextureView texture, wis::ShaderRe break; } - wis::com_ptr heap; D3D12_DESCRIPTOR_HEAP_DESC heap_desc{ .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, .NumDescriptors = 1, @@ -602,9 +633,9 @@ wis::ImplDX12Device::CreateShaderResource(DX12TextureView texture, wis::ShaderRe }; auto x = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - device->CreateDescriptorHeap(&heap_desc, heap.iid(), heap.put_void()); - device->CreateShaderResourceView(std::get<0>(texture), &srv_desc, heap->GetCPUDescriptorHandleForHeapStart()); - return wis::DX12ShaderResource{ std::move(heap) }; + device->CreateDescriptorHeap(&heap_desc, internal.heap.iid(), internal.heap.put_void()); + device->CreateShaderResourceView(std::get<0>(texture), &srv_desc, internal.heap->GetCPUDescriptorHandleForHeapStart()); + return out_resource; } bool wis::ImplDX12Device::QueryFeatureSupport(wis::DeviceFeature feature) const noexcept @@ -629,9 +660,12 @@ bool wis::ImplDX12Device::QueryFeatureSupport(wis::DeviceFeature feature) const } } -wis::ResultValue -wis::ImplDX12Device::CreateDescriptorStorage(wis::DescriptorStorageDesc desc) const noexcept +wis::DX12DescriptorStorage +wis::ImplDX12Device::CreateDescriptorStorage(wis::Result& result, const wis::DescriptorStorageDesc& desc) const noexcept { + DX12DescriptorStorage out_storage; + auto& internal = out_storage.GetMutableInternal(); + uint32_t size_resources = desc.cbuffer_count + desc.sbuffer_count + desc.stexture_count + desc.texture_count + desc.rbuffer_count; uint32_t size_samplers = desc.sampler_count; @@ -653,37 +687,40 @@ wis::ImplDX12Device::CreateDescriptorStorage(wis::DescriptorStorageDesc desc) co .NodeMask = 0u }; - wis::Internal storage{}; if (size_resources) { // create resource heap - auto hr = device->CreateDescriptorHeap(&resource_heap_desc, __uuidof(*storage.heap_resource), storage.heap_resource.put_void()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); + auto hr = device->CreateDescriptorHeap(&resource_heap_desc, __uuidof(*internal.heap_resource), internal.heap_resource.put_void()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_storage; + } - storage.heap_resource_increment = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - storage.heap_starts[1] = storage.heap_resource->GetCPUDescriptorHandleForHeapStart(); - storage.heap_gpu_starts[0] = storage.heap_resource->GetGPUDescriptorHandleForHeapStart(); + internal.heap_resource_increment = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + internal.heap_starts[1] = internal.heap_resource->GetCPUDescriptorHandleForHeapStart(); + internal.heap_gpu_starts[0] = internal.heap_resource->GetGPUDescriptorHandleForHeapStart(); for (uint32_t i = 2; i < sizes.size(); i++) { // first one is sampler - storage.heap_starts[i] = + internal.heap_starts[i] = sizes[i] - ? CD3DX12_CPU_DESCRIPTOR_HANDLE(storage.heap_starts[i - 1], sizes[i - 1], storage.heap_resource_increment) + ? CD3DX12_CPU_DESCRIPTOR_HANDLE(internal.heap_starts[i - 1], sizes[i - 1], internal.heap_resource_increment) : CD3DX12_CPU_DESCRIPTOR_HANDLE(); } } if (size_samplers) { // create sampler heap - auto hr = device->CreateDescriptorHeap(&sampler_heap_desc, __uuidof(*storage.heap_sampler), storage.heap_sampler.put_void()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); - storage.heap_sampler_increment = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); - storage.heap_starts[0] = storage.heap_sampler->GetCPUDescriptorHandleForHeapStart(); - storage.heap_gpu_starts[1] = storage.heap_sampler->GetGPUDescriptorHandleForHeapStart(); + auto hr = device->CreateDescriptorHeap(&sampler_heap_desc, __uuidof(*internal.heap_sampler), internal.heap_sampler.put_void()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_storage; + } + internal.heap_sampler_increment = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + internal.heap_starts[0] = internal.heap_sampler->GetCPUDescriptorHandleForHeapStart(); + internal.heap_gpu_starts[1] = internal.heap_sampler->GetGPUDescriptorHandleForHeapStart(); } - storage.device = device; + internal.device = device; - return DX12DescriptorStorage{ std::move(storage) }; + return out_storage; } namespace wis::detail { @@ -704,21 +741,28 @@ constexpr inline D3D12_ROOT_PARAMETER_TYPE to_dx(wis::DescriptorType type) noexc } } // namespace wis::detail -wis::ResultValue -wis::ImplDX12Device::CreateRootSignature(const wis::PushConstant* constants, +wis::DX12RootSignature +wis::ImplDX12Device::CreateRootSignature(wis::Result& result, + const wis::PushConstant* constants, uint32_t constants_size, const PushDescriptor* push_descriptors, uint32_t push_descriptors_size, uint32_t space_overlap_count) const noexcept { + DX12RootSignature out_signature; + auto& internal = out_signature.GetMutableInternal(); + if (constants_size > wis::max_push_constants) { - return wis::make_result(E_INVALIDARG); + result = wis::make_result(E_INVALIDARG); + return out_signature; } if (push_descriptors_size > wis::max_push_descriptors) { - return wis::make_result(E_INVALIDARG); + result = wis::make_result(E_INVALIDARG); + return out_signature; } if (space_overlap_count > wis::max_descriptor_space_overlap) { - return wis::make_result(E_INVALIDARG); + result = wis::make_result(E_INVALIDARG); + return out_signature; } uint32_t push_constants_count = constants_size; @@ -802,17 +846,22 @@ wis::ImplDX12Device::CreateRootSignature(const wis::PushConstant* constants, wis::com_ptr error; HRESULT hr = D3D12SerializeVersionedRootSignature(&desc, signature.put(), error.put()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); - - wis::com_ptr rsig; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_signature; + } hr = device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), - __uuidof(*rsig), rsig.put_void()); + internal.root.iid(), internal.root.put_void()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_signature; + } + internal.stage_map = stage_map; + internal.push_constant_count = push_constants_count; + internal.push_descriptor_count = push_descriptors_count; - return DX12RootSignature{ std::move(rsig), stage_map, push_constants_count, push_descriptors_count }; + return out_signature; } namespace wis::detail { @@ -845,18 +894,23 @@ inline constexpr uint32_t allocate_space( } } // namespace wis::detail -wis::ResultValue -wis::ImplDX12Device::CreateRootSignature2(const wis::PushConstant* push_constants, +wis::DX12RootSignature +wis::ImplDX12Device::CreateRootSignature2(wis::Result& result, const wis::PushConstant* push_constants, uint32_t constants_count, const wis::PushDescriptor* push_descriptors, uint32_t push_descriptors_count, const wis::DescriptorSpacing* descriptor_spacing) const noexcept { + DX12RootSignature out_state; + auto& internal = out_state.GetMutableInternal(); + if (constants_count > wis::max_push_constants) { - return wis::make_result(E_INVALIDARG); + result = wis::make_result(E_INVALIDARG); + return out_state; } if (push_descriptors_count > wis::max_push_descriptors) { - return wis::make_result(E_INVALIDARG); + result = wis::make_result(E_INVALIDARG); + return out_state; } wis::DescriptorSpacing default_spacing{}; if (!descriptor_spacing) { @@ -928,17 +982,21 @@ wis::ImplDX12Device::CreateRootSignature2(const wis::PushConstant* push_constant wis::com_ptr error; HRESULT hr = D3D12SerializeVersionedRootSignature(&desc, signature.put(), error.put()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); - - wis::com_ptr rsig; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_state; + } hr = device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), - __uuidof(*rsig), rsig.put_void()); + internal.root.iid(), internal.root.put_void()); - if (!wis::succeeded(hr)) - return wis::make_result(hr); - - return DX12RootSignature{ std::move(rsig), stage_map, push_constants_count, push_descriptors_count }; + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_state; + } + internal.stage_map = stage_map; + internal.push_constant_count = push_constants_count; + internal.push_descriptor_count = push_descriptors_count; + return out_state; } #endif // !DX12_DEVICE_CPP diff --git a/wisdom/include/wisdom/dx12/impl/dx12_factory.cpp b/wisdom/include/wisdom/dx12/impl/dx12_factory.cpp index df813d4d..70067498 100644 --- a/wisdom/include/wisdom/dx12/impl/dx12_factory.cpp +++ b/wisdom/include/wisdom/dx12/impl/dx12_factory.cpp @@ -3,66 +3,38 @@ #include #include -wis::ImplDX12Factory::ImplDX12Factory(wis::com_ptr factory) noexcept - : QueryInternal(std::move(factory)) +wis::DX12Factory +wis::ImplDX12CreateFactory(wis::Result& res, bool enable_debug, DX12FactoryExtension** extensions, size_t extension_count) noexcept { -} - -wis::ResultValue -wis::ImplDX12CreateFactory(bool enable_debug, DX12FactoryExtension** extensions, size_t extension_count) noexcept -{ - std::span exts{ - extensions, extensions + extension_count - }; + // Enable RVO + DX12Factory f; + auto& internal = f.GetMutableInternal(); - wis::com_ptr factory; - auto hr = CreateDXGIFactory2(enable_debug * DXGI_CREATE_FACTORY_DEBUG, __uuidof(*factory), - factory.put_void()); + auto hr = CreateDXGIFactory2(enable_debug * DXGI_CREATE_FACTORY_DEBUG, internal.factory.iid(), + internal.factory.put_void()); if (!wis::succeeded(hr)) { - hr = CreateDXGIFactory2(enable_debug * DXGI_CREATE_FACTORY_DEBUG, __uuidof(IDXGIFactory4), - factory.put_void()); - DX12Factory::has_preference = false; - if (!wis::succeeded(hr)) { - return wis::make_result(hr); - } + res = wis::make_result(hr); + return f; } - auto f = DX12Factory(std::move(factory)); - for (auto ext : exts) { + for (auto ext : std::span{ extensions, extension_count }) { ext->Init(f); } - return std::move(f); + return f; } -wis::ResultValue -wis::ImplDX12Factory::GetAdapter(uint32_t index, AdapterPreference preference) const noexcept +wis::DX12Adapter +wis::ImplDX12Factory::GetAdapter(wis::Result& result, uint32_t index, AdapterPreference preference) const noexcept { - auto gen = has_preference ? GetAdapterByGPUPreference(index, convert_dx(preference)) - : GetAdapter1(index); - - if (!gen) - return wis::make_result(gen.result); + wis::DX12Adapter adapter; + auto& internal = adapter.GetMutableInternal(); - return wis::DX12Adapter(std::move(gen.ptr)); -} - -wis::com_with_result -wis::ImplDX12Factory::GetAdapterByGPUPreference(uint32_t index, - DXGI_GPU_PREFERENCE preference) const noexcept -{ - wis::com_ptr adapter; - auto hr = factory->EnumAdapterByGpuPreference(index, preference, __uuidof(*adapter), - adapter.put_void()); - return { hr, std::move(adapter) }; -} - -wis::com_with_result -wis::ImplDX12Factory::GetAdapter1(uint32_t index) const noexcept -{ - wis::com_ptr adapter; - auto hr = factory->EnumAdapters1(index, adapter.put()); - return { hr, std::move(adapter) }; + auto hr = factory->EnumAdapterByGpuPreference(index, convert_dx(preference), internal.adapter.iid(), + internal.adapter.put_void()); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + } + return adapter; } - #endif // !DX12_FACTORY_CPP diff --git a/wisdom/include/wisdom/dx12/impl/dx12_fence.cpp b/wisdom/include/wisdom/dx12/impl/dx12_fence.cpp index 46fabbee..14129902 100644 --- a/wisdom/include/wisdom/dx12/impl/dx12_fence.cpp +++ b/wisdom/include/wisdom/dx12/impl/dx12_fence.cpp @@ -4,14 +4,18 @@ wis::Result wis::ImplDX12Fence::Wait(uint64_t value, uint64_t wait_ns) const noexcept { - if (GetCompletedValue() >= value) + if (GetCompletedValue() >= value) { return wis::success; + } HRESULT hr = fence->SetEventOnCompletion(value, fence_event.get()); - if (!succeeded(hr)) + if (!succeeded(hr)) { return wis::make_result(hr); + } - auto st = fence_event.wait(uint32_t(wait_ns / 1000)); + auto st = fence_event.wait(wait_ns == std::numeric_limits::max() + ? std::numeric_limits::max() + : uint32_t(wait_ns / 1000)); return st == wis::Status::Timeout ? wis::Result{ st, "Wait timed out" } : st != wis::Status::Error ? wis::success : wis::make_result(E_FAIL); diff --git a/wisdom/include/wisdom/dx12/impl/dx12_swapchain.cpp b/wisdom/include/wisdom/dx12/impl/dx12_swapchain.cpp index 0b788a64..6444feb6 100644 --- a/wisdom/include/wisdom/dx12/impl/dx12_swapchain.cpp +++ b/wisdom/include/wisdom/dx12/impl/dx12_swapchain.cpp @@ -16,17 +16,17 @@ wis::Result wis::detail::DX12SwapChainCreateInfo::InitBackBuffers() noexcept if (frame_count > back_buffer_count) { back_buffers = wis::detail::make_unique_for_overwrite(frame_count); - if (!back_buffers) + if (!back_buffers) { return wis::make_result(E_OUTOFMEMORY); + } } for (uint32_t n = 0; n < frame_count; n++) { - wis::com_ptr rc; - if (!succeeded(chain->GetBuffer(n, __uuidof(ID3D12Resource), rc.put_void()))) { + auto& bb_internal = back_buffers[n].GetMutableInternal(); + if (!succeeded(chain->GetBuffer(n, __uuidof(*bb_internal.resource), bb_internal.resource.put_void()))) { back_buffer_count = n + 1; break; } - back_buffers[n] = wis::DX12Texture(std::move(rc), nullptr, nullptr); } back_buffer_count = frame_count; return wis::success; @@ -34,8 +34,9 @@ wis::Result wis::detail::DX12SwapChainCreateInfo::InitBackBuffers() noexcept wis::Result wis::ImplDX12SwapChain::Resize(uint32_t width, uint32_t height) noexcept { - if (width == 0 || height == 0) + if (width == 0 || height == 0) { return wis::make_result(E_INVALIDARG); + } for (uint32_t n = 0; n < back_buffer_count; n++) { back_buffers[n] = {}; @@ -47,15 +48,16 @@ wis::Result wis::ImplDX12SwapChain::Resize(uint32_t width, uint32_t height) noex DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT | DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING * uint32_t(tearing)); - if (!wis::succeeded(hr)) + if (!wis::succeeded(hr)) { return wis::make_result(hr); + } for (uint32_t n = 0; n < back_buffer_count; n++) { - wis::com_ptr rc; - if (!wis::succeeded(hr = chain->GetBuffer(n, __uuidof(ID3D12Resource), rc.put_void()))) - return wis::make_result(hr); - - back_buffers[n] = wis::DX12Texture(std::move(rc), nullptr, nullptr); + auto& bb_internal = back_buffers[n].GetMutableInternal(); + if (!succeeded(chain->GetBuffer(n, __uuidof(*bb_internal.resource), bb_internal.resource.put_void()))) { + back_buffer_count = n + 1; + break; + } } return wis::success; } diff --git a/wisdom/include/wisdom/generated/api/api.h b/wisdom/include/wisdom/generated/api/api.hpp similarity index 98% rename from wisdom/include/wisdom/generated/api/api.h rename to wisdom/include/wisdom/generated/api/api.hpp index 80100b03..77f8d5dd 100644 --- a/wisdom/include/wisdom/generated/api/api.h +++ b/wisdom/include/wisdom/generated/api/api.hpp @@ -2,10 +2,11 @@ #pragma once #include #include +#include /** \mainpage Wisdom API Documentation -Version 0.4.0 +Version 0.5.0 Copyright (c) 2024 Ilya Doroshenko. All rights reserved. License: MIT @@ -1206,6 +1207,7 @@ enum class FactoryExtID : uint32_t { enum class DeviceExtID : uint32_t { Custom = 0, ///< Custom provided extension. Default initialization of the extension is done by user. DescriptorBufferExtension = 1, + ExtendedAllocation = 2, }; /** @@ -1901,21 +1903,41 @@ struct ResultValue { Result status; RetTy value; - constexpr ResultValue(RetTy value) noexcept - : status(success), value(std::move(value)) { } - constexpr ResultValue(Result status) noexcept - : status(status) { } - constexpr ResultValue(Result status, RetTy value) noexcept - : status(status), value(std::move(value)) { } + constexpr ResultValue() noexcept = default; + constexpr ResultValue(wis::Result status) noexcept + : status(status) + { + } + + template + requires std::is_member_function_pointer_v + constexpr ResultValue(Callable&& f, Callee* self, Args&&... args) noexcept + : value(std::invoke(f, self, status, std::forward(args)...)) + { + } + template + constexpr ResultValue(Callable&& f, Args&&... args) noexcept + : value(f(status, std::forward(args)...)) + { + } + + template + static constexpr ResultValue from_member_func(Callable&& f, Callee* self, Args&&... args) noexcept + { + ResultValue rv; + rv.value = std::invoke(f, self, rv.status, std::forward(args)...); + return rv; + } }; template constexpr decltype(auto) get(ResultValue& rv) noexcept { - if constexpr (s == 0) + if constexpr (s == 0) { return std::forward(rv.status); - else + } else { return std::forward(rv.value); + } } } // namespace wis diff --git a/wisdom/include/wisdom/generated/dx12/dx12_structs.hpp b/wisdom/include/wisdom/generated/dx12/dx12_structs.hpp index 7b4065b9..d2016974 100644 --- a/wisdom/include/wisdom/generated/dx12/dx12_structs.hpp +++ b/wisdom/include/wisdom/generated/dx12/dx12_structs.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include #include @@ -367,135 +367,187 @@ inline constexpr DXGI_FORMAT convert_dx(IndexType value) noexcept inline constexpr D3D12MA::ALLOCATION_FLAGS convert_dx(MemoryFlags value) noexcept { D3D12MA::ALLOCATION_FLAGS output = {}; - if (value & MemoryFlags::DedicatedAllocation) + if (value & MemoryFlags::DedicatedAllocation) { output |= D3D12MA::ALLOCATION_FLAG_COMMITTED; - if (value & MemoryFlags::Mapped) + } + if (value & MemoryFlags::Mapped) { output |= D3D12MA::ALLOCATION_FLAG_NONE; + } return output; } inline constexpr D3D12_BARRIER_SYNC convert_dx(BarrierSync value) noexcept { D3D12_BARRIER_SYNC output = {}; - if (value & BarrierSync::All) + if (value & BarrierSync::All) { output |= D3D12_BARRIER_SYNC_ALL; - if (value & BarrierSync::Draw) + } + if (value & BarrierSync::Draw) { output |= D3D12_BARRIER_SYNC_DRAW; - if (value & BarrierSync::IndexInput) + } + if (value & BarrierSync::IndexInput) { output |= D3D12_BARRIER_SYNC_INDEX_INPUT; - if (value & BarrierSync::VertexShading) + } + if (value & BarrierSync::VertexShading) { output |= D3D12_BARRIER_SYNC_VERTEX_SHADING; - if (value & BarrierSync::PixelShading) + } + if (value & BarrierSync::PixelShading) { output |= D3D12_BARRIER_SYNC_PIXEL_SHADING; - if (value & BarrierSync::DepthStencil) + } + if (value & BarrierSync::DepthStencil) { output |= D3D12_BARRIER_SYNC_DEPTH_STENCIL; - if (value & BarrierSync::RenderTarget) + } + if (value & BarrierSync::RenderTarget) { output |= D3D12_BARRIER_SYNC_RENDER_TARGET; - if (value & BarrierSync::Compute) + } + if (value & BarrierSync::Compute) { output |= D3D12_BARRIER_SYNC_COMPUTE_SHADING; - if (value & BarrierSync::Raytracing) + } + if (value & BarrierSync::Raytracing) { output |= D3D12_BARRIER_SYNC_RAYTRACING; - if (value & BarrierSync::Copy) + } + if (value & BarrierSync::Copy) { output |= D3D12_BARRIER_SYNC_COPY; - if (value & BarrierSync::Resolve) + } + if (value & BarrierSync::Resolve) { output |= D3D12_BARRIER_SYNC_RESOLVE; - if (value & BarrierSync::ExecuteIndirect) + } + if (value & BarrierSync::ExecuteIndirect) { output |= D3D12_BARRIER_SYNC_EXECUTE_INDIRECT; - if (value & BarrierSync::AllShading) + } + if (value & BarrierSync::AllShading) { output |= D3D12_BARRIER_SYNC_ALL_SHADING; - if (value & BarrierSync::NonPixelShading) + } + if (value & BarrierSync::NonPixelShading) { output |= D3D12_BARRIER_SYNC_NON_PIXEL_SHADING; - if (value & BarrierSync::ClearUAV) + } + if (value & BarrierSync::ClearUAV) { output |= D3D12_BARRIER_SYNC_CLEAR_UNORDERED_ACCESS_VIEW; - if (value & BarrierSync::VideoDecode) + } + if (value & BarrierSync::VideoDecode) { output |= D3D12_BARRIER_SYNC_VIDEO_DECODE; - if (value & BarrierSync::VideoEncode) + } + if (value & BarrierSync::VideoEncode) { output |= D3D12_BARRIER_SYNC_VIDEO_ENCODE; - if (value & BarrierSync::BuildRTAS) + } + if (value & BarrierSync::BuildRTAS) { output |= D3D12_BARRIER_SYNC_BUILD_RAYTRACING_ACCELERATION_STRUCTURE; - if (value & BarrierSync::CopyRTAS) + } + if (value & BarrierSync::CopyRTAS) { output |= D3D12_BARRIER_SYNC_COPY_RAYTRACING_ACCELERATION_STRUCTURE; + } return output; } inline constexpr D3D12_BARRIER_ACCESS convert_dx(ResourceAccess value) noexcept { D3D12_BARRIER_ACCESS output = {}; - if (value & ResourceAccess::VertexBuffer) + if (value & ResourceAccess::VertexBuffer) { output |= D3D12_BARRIER_ACCESS_VERTEX_BUFFER; - if (value & ResourceAccess::ConstantBuffer) + } + if (value & ResourceAccess::ConstantBuffer) { output |= D3D12_BARRIER_ACCESS_CONSTANT_BUFFER; - if (value & ResourceAccess::IndexBuffer) + } + if (value & ResourceAccess::IndexBuffer) { output |= D3D12_BARRIER_ACCESS_INDEX_BUFFER; - if (value & ResourceAccess::RenderTarget) + } + if (value & ResourceAccess::RenderTarget) { output |= D3D12_BARRIER_ACCESS_RENDER_TARGET; - if (value & ResourceAccess::UnorderedAccess) + } + if (value & ResourceAccess::UnorderedAccess) { output |= D3D12_BARRIER_ACCESS_UNORDERED_ACCESS; - if (value & ResourceAccess::DepthWrite) + } + if (value & ResourceAccess::DepthWrite) { output |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE; - if (value & ResourceAccess::DepthRead) + } + if (value & ResourceAccess::DepthRead) { output |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_READ; - if (value & ResourceAccess::ShaderResource) + } + if (value & ResourceAccess::ShaderResource) { output |= D3D12_BARRIER_ACCESS_SHADER_RESOURCE; - if (value & ResourceAccess::StreamOutput) + } + if (value & ResourceAccess::StreamOutput) { output |= D3D12_BARRIER_ACCESS_STREAM_OUTPUT; - if (value & ResourceAccess::IndirectArgument) + } + if (value & ResourceAccess::IndirectArgument) { output |= D3D12_BARRIER_ACCESS_INDIRECT_ARGUMENT; - if (value & ResourceAccess::CopyDest) + } + if (value & ResourceAccess::CopyDest) { output |= D3D12_BARRIER_ACCESS_COPY_DEST; - if (value & ResourceAccess::CopySource) + } + if (value & ResourceAccess::CopySource) { output |= D3D12_BARRIER_ACCESS_COPY_SOURCE; - if (value & ResourceAccess::ConditionalRendering) + } + if (value & ResourceAccess::ConditionalRendering) { output |= D3D12_BARRIER_ACCESS_PREDICATION; - if (value & ResourceAccess::AccelerationStrucureRead) + } + if (value & ResourceAccess::AccelerationStrucureRead) { output |= D3D12_BARRIER_ACCESS_RAYTRACING_ACCELERATION_STRUCTURE_READ; - if (value & ResourceAccess::AccelerationStrucureWrite) + } + if (value & ResourceAccess::AccelerationStrucureWrite) { output |= D3D12_BARRIER_ACCESS_RAYTRACING_ACCELERATION_STRUCTURE_WRITE; - if (value & ResourceAccess::ShadingRate) + } + if (value & ResourceAccess::ShadingRate) { output |= D3D12_BARRIER_ACCESS_SHADING_RATE_SOURCE; - if (value & ResourceAccess::VideoDecodeRead) + } + if (value & ResourceAccess::VideoDecodeRead) { output |= D3D12_BARRIER_ACCESS_VIDEO_DECODE_READ; - if (value & ResourceAccess::VideoDecodeWrite) + } + if (value & ResourceAccess::VideoDecodeWrite) { output |= D3D12_BARRIER_ACCESS_VIDEO_DECODE_WRITE; - if (value & ResourceAccess::ResolveDest) + } + if (value & ResourceAccess::ResolveDest) { output |= D3D12_BARRIER_ACCESS_RESOLVE_DEST; - if (value & ResourceAccess::ResolveSource) + } + if (value & ResourceAccess::ResolveSource) { output |= D3D12_BARRIER_ACCESS_RESOLVE_SOURCE; - if (value & ResourceAccess::NoAccess) + } + if (value & ResourceAccess::NoAccess) { output |= D3D12_BARRIER_ACCESS_NO_ACCESS; + } return output; } inline constexpr D3D12_RENDER_PASS_FLAGS convert_dx(RenderPassFlags value) noexcept { D3D12_RENDER_PASS_FLAGS output = {}; - if (value & RenderPassFlags::Suspending) + if (value & RenderPassFlags::Suspending) { output |= D3D12_RENDER_PASS_FLAG_SUSPENDING_PASS; - if (value & RenderPassFlags::Resuming) + } + if (value & RenderPassFlags::Resuming) { output |= D3D12_RENDER_PASS_FLAG_RESUMING_PASS; + } return output; } inline constexpr D3D12_RESOURCE_FLAGS convert_dx(TextureUsage value) noexcept { D3D12_RESOURCE_FLAGS output = {}; - if (value & TextureUsage::RenderTarget) + if (value & TextureUsage::RenderTarget) { output |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - if (value & TextureUsage::DepthStencil) + } + if (value & TextureUsage::DepthStencil) { output |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; - if (value & TextureUsage::CopySrc) + } + if (value & TextureUsage::CopySrc) { output |= D3D12_RESOURCE_FLAG_NONE; - if (value & TextureUsage::CopyDst) + } + if (value & TextureUsage::CopyDst) { output |= D3D12_RESOURCE_FLAG_NONE; - if (value & TextureUsage::ShaderResource) + } + if (value & TextureUsage::ShaderResource) { output |= D3D12_RESOURCE_FLAG_NONE; - if (value & TextureUsage::UnorderedAccess) + } + if (value & TextureUsage::UnorderedAccess) { output |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; - if (value & TextureUsage::HostCopy) + } + if (value & TextureUsage::HostCopy) { output |= D3D12_RESOURCE_FLAG_NONE; + } return output; } inline constexpr D3D12_FENCE_FLAGS convert_dx(FenceFlags value) noexcept { D3D12_FENCE_FLAGS output = {}; - if (value & FenceFlags::Shared) + if (value & FenceFlags::Shared) { output |= D3D12_FENCE_FLAG_SHARED; + } return output; } inline constexpr D3D12_PIPELINE_STATE_FLAGS convert_dx(PipelineFlags value) noexcept diff --git a/wisdom/include/wisdom/generated/vulkan/vk_structs.hpp b/wisdom/include/wisdom/generated/vulkan/vk_structs.hpp index 5fa7b306..764942ef 100644 --- a/wisdom/include/wisdom/generated/vulkan/vk_structs.hpp +++ b/wisdom/include/wisdom/generated/vulkan/vk_structs.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include namespace wis { @@ -686,135 +686,187 @@ inline constexpr VkIndexType convert_vk(IndexType value) noexcept inline constexpr VmaAllocationCreateFlags convert_vk(MemoryFlags value) noexcept { VmaAllocationCreateFlags output = {}; - if (value & MemoryFlags::DedicatedAllocation) + if (value & MemoryFlags::DedicatedAllocation) { output |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; - if (value & MemoryFlags::Mapped) + } + if (value & MemoryFlags::Mapped) { output |= VMA_ALLOCATION_CREATE_MAPPED_BIT; + } return output; } inline constexpr VkPipelineStageFlags2 convert_vk(BarrierSync value) noexcept { VkPipelineStageFlags2 output = {}; - if (value & BarrierSync::All) + if (value & BarrierSync::All) { output |= VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT; - if (value & BarrierSync::Draw) + } + if (value & BarrierSync::Draw) { output |= VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT | VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT | VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; - if (value & BarrierSync::IndexInput) + } + if (value & BarrierSync::IndexInput) { output |= VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT; - if (value & BarrierSync::VertexShading) + } + if (value & BarrierSync::VertexShading) { output |= VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT; - if (value & BarrierSync::PixelShading) + } + if (value & BarrierSync::PixelShading) { output |= VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT; - if (value & BarrierSync::DepthStencil) + } + if (value & BarrierSync::DepthStencil) { output |= VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT; - if (value & BarrierSync::RenderTarget) + } + if (value & BarrierSync::RenderTarget) { output |= VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; - if (value & BarrierSync::Compute) + } + if (value & BarrierSync::Compute) { output |= VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; - if (value & BarrierSync::Raytracing) + } + if (value & BarrierSync::Raytracing) { output |= VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR; - if (value & BarrierSync::Copy) + } + if (value & BarrierSync::Copy) { output |= VK_PIPELINE_STAGE_2_COPY_BIT; - if (value & BarrierSync::Resolve) + } + if (value & BarrierSync::Resolve) { output |= VK_PIPELINE_STAGE_2_COPY_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_RESOLVE_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; - if (value & BarrierSync::ExecuteIndirect) + } + if (value & BarrierSync::ExecuteIndirect) { output |= VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; - if (value & BarrierSync::AllShading) + } + if (value & BarrierSync::AllShading) { output |= VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; - if (value & BarrierSync::NonPixelShading) + } + if (value & BarrierSync::NonPixelShading) { output |= VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; - if (value & BarrierSync::ClearUAV) + } + if (value & BarrierSync::ClearUAV) { output |= VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT; - if (value & BarrierSync::VideoDecode) + } + if (value & BarrierSync::VideoDecode) { output |= VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR; - if (value & BarrierSync::VideoEncode) + } + if (value & BarrierSync::VideoEncode) { output |= VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR; - if (value & BarrierSync::BuildRTAS) + } + if (value & BarrierSync::BuildRTAS) { output |= VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR; - if (value & BarrierSync::CopyRTAS) + } + if (value & BarrierSync::CopyRTAS) { output |= VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR; + } return output; } inline constexpr VkAccessFlags2 convert_vk(ResourceAccess value) noexcept { VkAccessFlags2 output = {}; - if (value & ResourceAccess::VertexBuffer) + if (value & ResourceAccess::VertexBuffer) { output |= VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT; - if (value & ResourceAccess::ConstantBuffer) + } + if (value & ResourceAccess::ConstantBuffer) { output |= VK_ACCESS_2_UNIFORM_READ_BIT; - if (value & ResourceAccess::IndexBuffer) + } + if (value & ResourceAccess::IndexBuffer) { output |= VK_ACCESS_2_INDEX_READ_BIT; - if (value & ResourceAccess::RenderTarget) + } + if (value & ResourceAccess::RenderTarget) { output |= VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT; - if (value & ResourceAccess::UnorderedAccess) + } + if (value & ResourceAccess::UnorderedAccess) { output |= VK_ACCESS_2_SHADER_WRITE_BIT | VK_ACCESS_2_SHADER_READ_BIT; - if (value & ResourceAccess::DepthWrite) + } + if (value & ResourceAccess::DepthWrite) { output |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - if (value & ResourceAccess::DepthRead) + } + if (value & ResourceAccess::DepthRead) { output |= VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT; - if (value & ResourceAccess::ShaderResource) + } + if (value & ResourceAccess::ShaderResource) { output |= VK_ACCESS_2_SHADER_READ_BIT; - if (value & ResourceAccess::StreamOutput) + } + if (value & ResourceAccess::StreamOutput) { output |= VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT; - if (value & ResourceAccess::IndirectArgument) + } + if (value & ResourceAccess::IndirectArgument) { output |= VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT; - if (value & ResourceAccess::CopyDest) + } + if (value & ResourceAccess::CopyDest) { output |= VK_ACCESS_2_TRANSFER_WRITE_BIT; - if (value & ResourceAccess::CopySource) + } + if (value & ResourceAccess::CopySource) { output |= VK_ACCESS_2_TRANSFER_READ_BIT; - if (value & ResourceAccess::ConditionalRendering) + } + if (value & ResourceAccess::ConditionalRendering) { output |= VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT; - if (value & ResourceAccess::AccelerationStrucureRead) + } + if (value & ResourceAccess::AccelerationStrucureRead) { output |= VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR; - if (value & ResourceAccess::AccelerationStrucureWrite) + } + if (value & ResourceAccess::AccelerationStrucureWrite) { output |= VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; - if (value & ResourceAccess::ShadingRate) + } + if (value & ResourceAccess::ShadingRate) { output |= VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR; - if (value & ResourceAccess::VideoDecodeRead) + } + if (value & ResourceAccess::VideoDecodeRead) { output |= VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR; - if (value & ResourceAccess::VideoDecodeWrite) + } + if (value & ResourceAccess::VideoDecodeWrite) { output |= VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR; - if (value & ResourceAccess::ResolveDest) + } + if (value & ResourceAccess::ResolveDest) { output |= VK_ACCESS_2_TRANSFER_WRITE_BIT | VK_ACCESS_2_SHADER_WRITE_BIT; - if (value & ResourceAccess::ResolveSource) + } + if (value & ResourceAccess::ResolveSource) { output |= VK_ACCESS_2_TRANSFER_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT; - if (value & ResourceAccess::NoAccess) + } + if (value & ResourceAccess::NoAccess) { output |= VK_ACCESS_2_NONE; + } return output; } inline constexpr VkRenderingFlags convert_vk(RenderPassFlags value) noexcept { VkRenderingFlags output = {}; - if (value & RenderPassFlags::Suspending) + if (value & RenderPassFlags::Suspending) { output |= VK_RENDERING_SUSPENDING_BIT; - if (value & RenderPassFlags::Resuming) + } + if (value & RenderPassFlags::Resuming) { output |= VK_RENDERING_RESUMING_BIT; + } return output; } inline constexpr VkImageUsageFlags convert_vk(TextureUsage value) noexcept { VkImageUsageFlags output = {}; - if (value & TextureUsage::RenderTarget) + if (value & TextureUsage::RenderTarget) { output |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - if (value & TextureUsage::DepthStencil) + } + if (value & TextureUsage::DepthStencil) { output |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - if (value & TextureUsage::CopySrc) + } + if (value & TextureUsage::CopySrc) { output |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - if (value & TextureUsage::CopyDst) + } + if (value & TextureUsage::CopyDst) { output |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; - if (value & TextureUsage::ShaderResource) + } + if (value & TextureUsage::ShaderResource) { output |= VK_IMAGE_USAGE_SAMPLED_BIT; - if (value & TextureUsage::UnorderedAccess) + } + if (value & TextureUsage::UnorderedAccess) { output |= VK_IMAGE_USAGE_STORAGE_BIT; - if (value & TextureUsage::HostCopy) + } + if (value & TextureUsage::HostCopy) { output |= VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT; + } return output; } inline constexpr VkPipelineCreateFlags convert_vk(PipelineFlags value) noexcept { VkPipelineCreateFlags output = {}; - if (value & PipelineFlags::DescriptorBuffer) + if (value & PipelineFlags::DescriptorBuffer) { output |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + } return output; } } // namespace wis diff --git a/wisdom/include/wisdom/global/internal.h b/wisdom/include/wisdom/global/internal.h index 3caa34c4..a01f020d 100644 --- a/wisdom/include/wisdom/global/internal.h +++ b/wisdom/include/wisdom/global/internal.h @@ -2,7 +2,49 @@ #include #include +#include +#include + namespace wis { +template +class atype +{ + static inline void xprint(std::source_location sl = std::source_location::current()) + { + if constexpr (enabled) { + std::printf("%s\n", sl.function_name()); + } + } + +public: + atype() + { + xprint(); + } + ~atype() + { + xprint(); + } + atype(const atype&) + { + xprint(); + } + atype(atype&&) noexcept + { + xprint(); + } + atype& operator=(atype&&) noexcept + { + xprint(); + return *this; + } + atype& operator=(const atype&) noexcept + { + xprint(); + return *this; + } +}; + /// @brief Template class for internal implementation /// @tparam Impl Implementation class type template @@ -12,7 +54,7 @@ struct Internal { /// @brief QueryInternal class for querying the internal implementation /// @tparam Impl Implementation class type, passed to Internal template -struct QueryInternal : protected Internal { +struct QueryInternal : protected Internal { /*, public atype*/ QueryInternal() = default; template @@ -27,6 +69,13 @@ struct QueryInternal : protected Internal { { return *this; } + + /// @brief Get the mutable internal implementation + /// @return Reference to the internal implementation + [[nodiscard]] Internal& GetMutableInternal() noexcept + { + return *this; + } }; template diff --git a/wisdom/include/wisdom/util/log_layer.h b/wisdom/include/wisdom/util/log_layer.h index 6374b1fd..484f6eac 100644 --- a/wisdom/include/wisdom/util/log_layer.h +++ b/wisdom/include/wisdom/util/log_layer.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include #include @@ -18,7 +18,7 @@ constexpr const char* severity_strings[]{ /// @brief Create a custom log layer to receive logging from the library struct LogLayer { virtual ~LogLayer() = default; - virtual void Log(Severity sev, std::string message, wis::source_location sl = wis::source_location::current()){}; + virtual void Log(Severity sev, std::string message, wis::source_location sl = wis::source_location::current()) {}; }; /// @brief Set the log layer for the library @@ -61,8 +61,9 @@ class LibLogger inline void lib_log_internal(Severity sev, std::string message, wis::source_location sl = wis::source_location::current()) { - if (auto log_ptr = LibLogger::Get()) + if (auto log_ptr = LibLogger::Get()) { log_ptr->Log(sev, std::move(message), sl); + } } // Compile time resolved loggong for library @@ -72,8 +73,9 @@ inline void lib_log_internal(Severity sev, std::string message, wis::source_loca /// @param sl Source location of the message inline void lib_debug(std::string message, wis::source_location sl = wis::source_location::current()) { - if constexpr (WISDOM_LOG_LEVEL <= uint32_t(Severity::Debug)) + if constexpr (WISDOM_LOG_LEVEL <= uint32_t(Severity::Debug)) { lib_log_internal(Severity::Debug, std::move(message), sl); + } } /// @brief Trace, this should be used for very detailed information @@ -81,8 +83,9 @@ inline void lib_debug(std::string message, wis::source_location sl = wis::source /// @param sl Source location of the message inline void lib_trace(std::string message, wis::source_location sl = wis::source_location::current()) { - if constexpr (WISDOM_LOG_LEVEL <= uint32_t(Severity::Trace)) + if constexpr (WISDOM_LOG_LEVEL <= uint32_t(Severity::Trace)) { lib_log_internal(Severity::Trace, std::move(message), sl); + } } /// @brief Information, this should be used for general information @@ -90,8 +93,9 @@ inline void lib_trace(std::string message, wis::source_location sl = wis::source /// @param sl Source location of the message inline void lib_info(std::string message, wis::source_location sl = wis::source_location::current()) { - if constexpr (WISDOM_LOG_LEVEL <= uint32_t(Severity::Info)) + if constexpr (WISDOM_LOG_LEVEL <= uint32_t(Severity::Info)) { lib_log_internal(Severity::Info, std::move(message), sl); + } } /// @brief Log a warning message to the library log layer @@ -99,8 +103,9 @@ inline void lib_info(std::string message, wis::source_location sl = wis::source_ /// @param sl Source location of the message inline void lib_warn(std::string message, wis::source_location sl = wis::source_location::current()) { - if constexpr (WISDOM_LOG_LEVEL <= uint32_t(Severity::Warning)) + if constexpr (WISDOM_LOG_LEVEL <= uint32_t(Severity::Warning)) { lib_log_internal(Severity::Warning, std::move(message), sl); + } } /// @brief Error, this should be used when the library is in a recoverable state @@ -108,8 +113,9 @@ inline void lib_warn(std::string message, wis::source_location sl = wis::source_ /// @param sl Source location of the message inline void lib_error(std::string message, wis::source_location sl = wis::source_location::current()) { - if constexpr (WISDOM_LOG_LEVEL <= +Severity::Error) + if constexpr (WISDOM_LOG_LEVEL <= +Severity::Error) { lib_log_internal(Severity::Error, std::move(message), sl); + } } /// @brief Critical error, this should be used when the library is in an unrecoverable state @@ -117,8 +123,9 @@ inline void lib_error(std::string message, wis::source_location sl = wis::source /// @param sl Source location of the message inline void lib_critical(std::string message, wis::source_location sl = wis::source_location::current()) { - if constexpr (WISDOM_LOG_LEVEL <= +Severity::Critical) + if constexpr (WISDOM_LOG_LEVEL <= +Severity::Critical) { lib_log_internal(Severity::Critical, std::move(message), sl); + } } /// @brief Log a message to the library log layer diff --git a/wisdom/include/wisdom/vulkan/impl/vk_adapter.cpp b/wisdom/include/wisdom/vulkan/impl/vk_adapter.cpp index 39617048..353d870d 100644 --- a/wisdom/include/wisdom/vulkan/impl/vk_adapter.cpp +++ b/wisdom/include/wisdom/vulkan/impl/vk_adapter.cpp @@ -9,8 +9,9 @@ wis::Result wis::ImplVKAdapter::GetDesc(AdapterDesc* pout_desc) const noexcept { - if (!pout_desc) - return wis::make_result(VK_ERROR_UNKNOWN); + if (!pout_desc) { + return wis::make_result<"AdapterDesc was nullptr ">(VK_ERROR_UNKNOWN); + } auto& out_desc = *pout_desc; auto& instance_table = instance.table(); @@ -50,15 +51,18 @@ wis::Result wis::ImplVKAdapter::GetDesc(AdapterDesc* pout_desc) const noexcept if (i.propertyFlags & VkMemoryPropertyFlagBits::VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { system_mem = memory_props.memoryHeaps[i.heapIndex].size; } - if ((system_mem != 0u) && (local_mem != 0u)) + if ((system_mem != 0u) && (local_mem != 0u)) { break; + } } AdapterFlags flag{}; - if (desc.deviceType & VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) + if (desc.deviceType & VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) { flag = AdapterFlags(flag | AdapterFlags::Remote); - if (desc.deviceType & VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU) + } + if (desc.deviceType & VkPhysicalDeviceType::VK_PHYSICAL_DEVICE_TYPE_CPU) { flag = AdapterFlags(flag | AdapterFlags::Software); + } std::strncpy(const_cast(out_desc.description.data()), desc.deviceName, sizeof(out_desc.description) - 1); diff --git a/wisdom/include/wisdom/vulkan/impl/vk_allocator.cpp b/wisdom/include/wisdom/vulkan/impl/vk_allocator.cpp index 76671226..56a6b3d9 100644 --- a/wisdom/include/wisdom/vulkan/impl/vk_allocator.cpp +++ b/wisdom/include/wisdom/vulkan/impl/vk_allocator.cpp @@ -18,8 +18,8 @@ constexpr static VkExternalMemoryImageCreateInfoKHR external_info_image{ }; } // namespace wis::detail -wis::ResultValue -wis::ImplVKResourceAllocator::CreateBuffer(uint64_t size, wis::BufferUsage usage, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept +wis::VKBuffer +wis::ImplVKResourceAllocator::CreateBuffer(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept { VkBufferCreateInfo desc; VKFillBufferDesc(size, usage, desc); @@ -45,11 +45,11 @@ wis::ImplVKResourceAllocator::CreateBuffer(uint64_t size, wis::BufferUsage usage .usage = VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO, .requiredFlags = wis::convert_vk(memory) }; - return VKCreateBuffer(desc, alloc); + return VKCreateBuffer(result, desc, alloc); } -wis::ResultValue -wis::ImplVKResourceAllocator::CreateTexture(const wis::TextureDesc& desc, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept +wis::VKTexture +wis::ImplVKResourceAllocator::CreateTexture(wis::Result& result, const wis::TextureDesc& desc, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept { VkImageCreateInfo img_desc; VKFillImageDesc(desc, img_desc); @@ -59,7 +59,7 @@ wis::ImplVKResourceAllocator::CreateTexture(const wis::TextureDesc& desc, wis::M .usage = VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO, .requiredFlags = wis::convert_vk(memory) }; - return VKCreateTexture(img_desc, alloc); + return VKCreateTexture(result, img_desc, alloc); } wis::AllocationInfo @@ -88,11 +88,14 @@ wis::ImplVKResourceAllocator::GetBufferAllocationInfo(uint64_t size, BufferUsage }; } -wis::ResultValue -wis::ImplVKResourceAllocator::AllocateTextureMemory(uint64_t size, wis::TextureUsage usage, +wis::VKMemory +wis::ImplVKResourceAllocator::AllocateTextureMemory(wis::Result& result, uint64_t size, wis::TextureUsage usage, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept { + VKMemory out_mem; + auto& internal = out_mem.GetMutableInternal(); + VkMemoryRequirements2 req; VKFillTextureAllocationInfo({ .format = wis::DataFormat::RGBA8Unorm, @@ -122,20 +125,22 @@ wis::ImplVKResourceAllocator::AllocateTextureMemory(uint64_t size, wis::TextureU }; auto& alloc_ref = mem_flags & wis::MemoryFlags::Exportable ? export_memory_allocator : allocator; + auto vr = vmaAllocateMemory(alloc_ref.get(), &req.memoryRequirements, &alloc_desc, &internal.allocation, nullptr); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + } - VmaAllocation allocation; - auto result = vmaAllocateMemory(alloc_ref.get(), &req.memoryRequirements, &alloc_desc, &allocation, nullptr); - - if (!wis::succeeded(result)) - return wis::make_result(result); - - return VKMemory{ alloc_ref, allocation }; + internal.allocator = alloc_ref; + return out_mem; } -wis::ResultValue -wis::ImplVKResourceAllocator::AllocateBufferMemory(uint64_t size, wis::BufferUsage usage, +wis::VKMemory +wis::ImplVKResourceAllocator::AllocateBufferMemory(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory, wis::MemoryFlags mem_flags) const noexcept { + VKMemory out_mem; + auto& internal = out_mem.GetMutableInternal(); + VkMemoryRequirements2 req{}; VKFillBufferAllocationInfo(size, usage, req); @@ -160,21 +165,26 @@ wis::ImplVKResourceAllocator::AllocateBufferMemory(uint64_t size, wis::BufferUsa .usage = vma_usage, .requiredFlags = wis::convert_vk(memory), }; - VmaAllocation allocation; - auto result = vmaAllocateMemory(alloc_ref.get(), &req.memoryRequirements, &alloc_desc, &allocation, nullptr); + auto vr = vmaAllocateMemory(alloc_ref.get(), &req.memoryRequirements, &alloc_desc, &internal.allocation, nullptr); - if (!wis::succeeded(result)) - return wis::make_result(result); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return out_mem; + } - return VKMemory{ alloc_ref, allocation }; + internal.allocator = alloc_ref; + return out_mem; } -wis::ResultValue -wis::ImplVKResourceAllocator::PlaceBuffer(wis::VKMemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept +wis::VKBuffer +wis::ImplVKResourceAllocator::PlaceBuffer(wis::Result& result, wis::VKMemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept { + VKBuffer out_buffer; auto al1 = std::get<0>(memory); - if (al1 != allocator.get() && al1 != export_memory_allocator.get()) - return wis::make_result(VK_ERROR_UNKNOWN); + if (al1 != allocator.get() && al1 != export_memory_allocator.get()) { + result = wis::make_result(VK_ERROR_UNKNOWN); + return out_buffer; + } VkBufferCreateInfo desc; VKFillBufferDesc(size, usage, desc); @@ -184,15 +194,19 @@ wis::ImplVKResourceAllocator::PlaceBuffer(wis::VKMemoryView memory, uint64_t mem desc.pNext = &detail::external_info_buffer; } - return VKCreateAliasingBuffer(desc, memory_offset, std::get<1>(memory), interop); + out_buffer = VKCreateAliasingBuffer(result, desc, memory_offset, std::get<1>(memory), interop); + return out_buffer; } -wis::ResultValue -wis::ImplVKResourceAllocator::PlaceTexture(wis::VKMemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept +wis::VKTexture +wis::ImplVKResourceAllocator::PlaceTexture(wis::Result& result, wis::VKMemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept { + VKTexture out_buffer; auto al1 = std::get<0>(memory); - if (al1 != allocator.get() && al1 != export_memory_allocator.get()) - return wis::make_result(VK_ERROR_UNKNOWN); + if (al1 != allocator.get() && al1 != export_memory_allocator.get()) { + result = wis::make_result(VK_ERROR_UNKNOWN); + return out_buffer; + } VkImageCreateInfo img_desc; VKFillImageDesc(desc, img_desc); @@ -202,82 +216,112 @@ wis::ImplVKResourceAllocator::PlaceTexture(wis::VKMemoryView memory, uint64_t me img_desc.pNext = &detail::external_info_image; } - return VKCreateAliasingTexture(img_desc, memory_offset, std::get<1>(memory), interop); + out_buffer = VKCreateAliasingTexture(result, img_desc, memory_offset, std::get<1>(memory), interop); + return out_buffer; } // ========================================================================================= -wis::ResultValue -wis::ImplVKResourceAllocator::VKCreateTexture(VkImageCreateInfo& desc, const VmaAllocationCreateInfo& alloc_desc, bool interop) const noexcept +wis::VKTexture +wis::ImplVKResourceAllocator::VKCreateTexture(wis::Result& result, VkImageCreateInfo& desc, const VmaAllocationCreateInfo& alloc_desc, bool interop) const noexcept { - if (interop && !export_memory_allocator) - return wis::make_result(VK_ERROR_UNKNOWN); + VKTexture out_texture; + auto& internal = out_texture.GetMutableInternal(); + auto& memory_internal = internal.memory.GetMutableInternal(); + + if (interop && !export_memory_allocator) { + result = wis::make_result(VK_ERROR_UNKNOWN); + return out_texture; + } - VmaAllocation allocation; - VkImage buffer; + auto& xallocator = interop ? export_memory_allocator : allocator; - auto result = vmaCreateImage( - allocator.get(), + auto vr = vmaCreateImage( + xallocator.get(), reinterpret_cast(&desc), &alloc_desc, - &buffer, - &allocation, + &internal.buffer, + &memory_internal.allocation, nullptr); - if (!wis::succeeded(result)) - return wis::make_result(result); - - return VKTexture{ desc.format, buffer, { desc.extent.width, desc.extent.height }, allocator, allocation }; + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return out_texture; + } + memory_internal.allocator = xallocator; + internal.format = desc.format; + internal.size = { desc.extent.width, desc.extent.height }; + return out_texture; } -wis::ResultValue -wis::ImplVKResourceAllocator::VKCreateBuffer(VkBufferCreateInfo& desc, const VmaAllocationCreateInfo& alloc_desc, bool interop) const noexcept +wis::VKBuffer +wis::ImplVKResourceAllocator::VKCreateBuffer(wis::Result& result, VkBufferCreateInfo& desc, const VmaAllocationCreateInfo& alloc_desc, bool interop) const noexcept { - if (interop && !export_memory_allocator) - return wis::make_result(VK_ERROR_UNKNOWN); + VKBuffer out_buffer; + auto& internal = out_buffer.GetMutableInternal(); + auto& memory_internal = internal.memory.GetMutableInternal(); + + if (interop && !export_memory_allocator) { + result = wis::make_result(VK_ERROR_UNKNOWN); + return out_buffer; + } + + auto& xallocator = interop ? export_memory_allocator : allocator; - VmaAllocation allocation; - VkBuffer buffer; - VkResult result = vmaCreateBuffer( - allocator.get(), + VkResult vr = vmaCreateBuffer( + xallocator.get(), &desc, &alloc_desc, - &buffer, - &allocation, + &internal.buffer, + &memory_internal.allocation, nullptr); - if (!wis::succeeded(result)) - return wis::make_result(result); - - return VKBuffer{ allocator, buffer, allocation }; + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return out_buffer; + } + memory_internal.allocator = xallocator; + return out_buffer; } -wis::ResultValue -wis::ImplVKResourceAllocator::VKCreateAliasingBuffer(VkBufferCreateInfo& desc, VkDeviceSize offset, VmaAllocation alloc, bool interop) const noexcept +wis::VKBuffer +wis::ImplVKResourceAllocator::VKCreateAliasingBuffer(wis::Result& result, VkBufferCreateInfo& desc, VkDeviceSize offset, VmaAllocation alloc, bool interop) const noexcept { + VKBuffer out_buffer; + auto& internal = out_buffer.GetMutableInternal(); + auto& alloc_ref = interop ? export_memory_allocator : allocator; - VkBuffer buffer; - auto res = vmaCreateAliasingBuffer2(alloc_ref.get(), alloc, offset, &desc, &buffer); + auto res = vmaCreateAliasingBuffer2(alloc_ref.get(), alloc, offset, &desc, &internal.buffer); if (!wis::succeeded(res)) { - return wis::make_result(res); + result = wis::make_result(res); + return out_buffer; } - return VKBuffer{ alloc_ref, buffer, nullptr }; + internal.memory.GetMutableInternal().allocator = alloc_ref; + return out_buffer; } -wis::ResultValue -wis::ImplVKResourceAllocator::VKCreateAliasingTexture(VkImageCreateInfo& desc, VkDeviceSize offset, VmaAllocation alloc, bool interop) const noexcept +wis::VKTexture +wis::ImplVKResourceAllocator::VKCreateAliasingTexture(wis::Result& result, VkImageCreateInfo& desc, VkDeviceSize offset, VmaAllocation alloc, bool interop) const noexcept { + VKTexture out_texture; + auto& internal = out_texture.GetMutableInternal(); + auto& memory_internal = internal.memory.GetMutableInternal(); + auto& alloc_ref = interop ? export_memory_allocator : allocator; - VkImage buffer; - auto res = vmaCreateAliasingImage2(alloc_ref.get(), alloc, offset, &desc, &buffer); + auto res = vmaCreateAliasingImage2(alloc_ref.get(), alloc, offset, &desc, &internal.buffer); if (!wis::succeeded(res)) { - return wis::make_result(res); + result = wis::make_result(res); + return out_texture; } - return VKTexture{ desc.format, buffer, { desc.extent.width, desc.extent.height }, alloc_ref, nullptr }; + memory_internal.allocator = alloc_ref; + + internal.format = desc.format; + internal.size = { desc.extent.width, desc.extent.height }; + return out_texture; } void wis::ImplVKResourceAllocator::VKFillBufferDesc(uint64_t size, wis::BufferUsage flags, VkBufferCreateInfo& info) noexcept diff --git a/wisdom/include/wisdom/vulkan/impl/vk_create_factory.cpp b/wisdom/include/wisdom/vulkan/impl/vk_create_factory.cpp index e2857692..05b63215 100644 --- a/wisdom/include/wisdom/vulkan/impl/vk_create_factory.cpp +++ b/wisdom/include/wisdom/vulkan/impl/vk_create_factory.cpp @@ -6,94 +6,107 @@ #include #include -wis::ResultValue> -wis::ImplVKFactory::FoundExtensions(std::span in_extensions) noexcept +wis::detail::fixed_allocation +wis::ImplVKFactory::FoundExtensions(wis::Result& result, std::span in_extensions) noexcept { auto& exts = detail::VKFactoryGlobals::Instance().instance_extensions; auto ext_string = [](const auto& ext) { std::string str = "All Extensions:\n"; - for (const auto& i : ext) + for (const auto& i : ext) { wis::format_to(std::back_inserter(str), "{},\n", i); + } return str; }; - if constexpr (wis::debug_mode) + if constexpr (wis::debug_mode) { wis::lib_info(ext_string(exts)); + } // Unique set of extensions std::unordered_set> exts_set; exts_set.reserve(in_extensions.size()); - for (const auto& i : in_extensions) + for (const auto& i : in_extensions) { exts_set.insert(i); + } // allocate a bit more than needed - auto found_extension = wis::detail::make_fixed_allocation(exts_set.size()); - if (!found_extension) - return wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + wis::detail::fixed_allocation found_extension = wis::detail::make_fixed_allocation(exts_set.size()); + if (!found_extension) { + result = wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + return found_extension; + } size_t index = 0; // O(n) for (auto extension : exts_set) { - if (exts.find(extension) != exts.end()) + if (exts.find(extension) != exts.end()) { found_extension[index++] = extension.data(); - else + } else { wis::lib_warn(wis::format("Extension {} not found", extension)); + } } found_extension.size = index; if constexpr (wis::debug_mode) { std::string debug_str{ "Used Extensions:\n" }; - for (const auto* i : found_extension) + for (const auto* i : found_extension) { wis::format_to(std::back_inserter(debug_str), "{},\n", i); + } wis::lib_info(std::move(debug_str)); } - return std::move(found_extension); + return found_extension; } -wis::ResultValue> -wis::ImplVKFactory::FoundLayers(std::span in_layers) noexcept +wis::detail::fixed_allocation +wis::ImplVKFactory::FoundLayers(wis::Result& result, std::span in_layers) noexcept { auto& exts = detail::VKFactoryGlobals::Instance().instance_layers; auto ext_string = [](const auto& ext) { std::string str = "All Layers:\n"; - for (const auto& i : ext) + for (const auto& i : ext) { wis::format_to(std::back_inserter(str), "{},\n", i); + } return str; }; - if constexpr (wis::debug_mode) + if constexpr (wis::debug_mode) { wis::lib_info(ext_string(exts)); + } std::unordered_set> layer_set; layer_set.reserve(in_layers.size()); - for (const auto& i : in_layers) + for (const auto& i : in_layers) { layer_set.insert(i); + } // allocate a bit more than needed auto found_layers = wis::detail::make_fixed_allocation(layer_set.size()); - if (!found_layers) - return wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); - + if (!found_layers) { + result = wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + return found_layers; + } size_t index = 0; // O(n) for (const auto layer : layer_set) { - if (exts.contains(layer)) + if (exts.contains(layer)) { found_layers[index++] = layer.data(); - else + } else { wis::lib_warn(wis::format("Layer {} not found", layer)); + } } found_layers.size = index; if constexpr (wis::debug_mode) { std::string debug_str{ "Used Layers:\n" }; - for (const auto* i : found_layers) + for (const auto* i : found_layers) { wis::format_to(std::back_inserter(debug_str), "{},\n", i); + } wis::lib_info(std::move(debug_str)); } @@ -101,9 +114,90 @@ wis::ImplVKFactory::FoundLayers(std::span in_layers) noexcept } //-------------------------------------------------------------------------------------------------- +namespace wis::detail { +inline wis::VKFactory +VKCreateFactoryWithExtensions(wis::Result& result, bool debug_layer, const char** exts, size_t extension_count, const char** layers, size_t layer_count) noexcept +{ + VKFactory out_factory; + auto& internal = out_factory.GetMutableInternal(); + + auto xr = detail::VKFactoryGlobals::Instance().InitializeFactoryGlobals(); + if (xr.status != wis::Status::Ok) { + result = xr; + return out_factory; + } + auto& gt = detail::VKFactoryGlobals::GetGlobalTable(); + + VkResult vr{}; + uint32_t version = 0; + if (gt.vkEnumerateInstanceVersion) { + vr = gt.vkEnumerateInstanceVersion(&version); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return out_factory; + } + } else { + version = VK_API_VERSION_1_0; + } + + wis::lib_info(wis::format("Vulkan version: {}.{}.{}", VK_API_VERSION_MAJOR(version), + VK_API_VERSION_MINOR(version), VK_API_VERSION_PATCH(version))); + + VkApplicationInfo info{ + VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, "", VK_MAKE_API_VERSION(0, 1, 0, 0), "", + VK_MAKE_API_VERSION(0, 1, 0, 0), version + }; + + auto found_extensions = VKFactory::FoundExtensions(result, { exts, exts + extension_count }); + if (result.status != wis::Status::Ok) { + return out_factory; + } + + auto found_layers = VKFactory::FoundLayers(result, { layers, layers + layer_count }); + if (result.status != wis::Status::Ok) { + return out_factory; + } + VkInstanceCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pApplicationInfo = &info, + .enabledLayerCount = uint32_t(found_layers.size), + .ppEnabledLayerNames = found_layers.get_data(), + .enabledExtensionCount = uint32_t(found_extensions.size), + .ppEnabledExtensionNames = found_extensions.get_data() }; + + VkInstance unsafe_instance; + vr = gt.vkCreateInstance(&create_info, nullptr, &unsafe_instance); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return out_factory; + } + auto destroy_instance = (PFN_vkDestroyInstance)gt.vkGetInstanceProcAddr(unsafe_instance, "vkDestroyInstance"); + wis::managed_handle safe_instance{ unsafe_instance, destroy_instance }; + + auto table = wis::detail::make_unique(); + if (!table) { + result = wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + return out_factory; + } + if (!table->Init(safe_instance.get(), gt.vkGetInstanceProcAddr)) { + result = wis::make_result(VK_ERROR_UNKNOWN); + return out_factory; + } + + internal.api_version = version; + internal.factory = wis::SharedInstance{ safe_instance.release(), destroy_instance, std::move(table), > }; + internal.debug_layer = debug_layer; -wis::ResultValue -wis::ImplVKCreateFactory(bool debug_layer, VKFactoryExtension** extensions, size_t extension_count) noexcept + vr = out_factory.VKEnumeratePhysicalDevices(); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + } + return out_factory; +} +} // namespace wis::detail + +//-------------------------------------------------------------------------------------------------- +wis::VKFactory +wis::ImplVKCreateFactory(wis::Result& result, bool debug_layer, VKFactoryExtension** extensions, size_t extension_count) noexcept { size_t ext_alloc_size = std::size(detail::instance_extensions); size_t layer_alloc_size = std::size(detail::instance_layers); @@ -141,101 +235,31 @@ wis::ImplVKCreateFactory(bool debug_layer, VKFactoryExtension** extensions, size auto ext = extensions[i]->GetRequiredExtensions(); auto layer = extensions[i]->GetRequiredLayers(); - if (ext.size() > 0) + if (ext.size() > 0) { std::copy(ext.begin(), ext.end(), ext_alloc_raw + index_ext); - if (layer.size() > 0) + } + if (layer.size() > 0) { std::copy(layer.begin(), layer.end(), layer_alloc_raw + index_layer); + } index_ext += ext.size(); index_layer += layer.size(); } - auto [resx, factory] = detail::VKCreateFactoryWithExtensions(debug_layer, ext_alloc_raw, ext_alloc_size, layer_alloc_raw, layer_alloc_size); - if (resx.status != wis::Status::Ok) - return resx; + auto factory = detail::VKCreateFactoryWithExtensions(result, debug_layer, ext_alloc_raw, ext_alloc_size, layer_alloc_raw, layer_alloc_size); + if (result.status != wis::Status::Ok) { + return factory; + } for (size_t i = 0; i < extension_count; i++) { auto res = extensions[i]->Init(factory); - if (res.status != wis::Status::Ok) - return res; + if (res.status != wis::Status::Ok) { + result = res; + return factory; + } } - return std::move(factory); + return factory; } -wis::ResultValue -wis::detail::VKCreateFactoryWithExtensions(bool debug_layer, const char** exts, size_t extension_count, const char** layers, size_t layer_count) noexcept -{ - auto xr = detail::VKFactoryGlobals::Instance().InitializeFactoryGlobals(); - if (xr.status != wis::Status::Ok) - return xr; - - auto& gt = detail::VKFactoryGlobals::GetGlobalTable(); - - VkResult vr{}; - uint32_t version = 0; - if (gt.vkEnumerateInstanceVersion) { - vr = gt.vkEnumerateInstanceVersion(&version); - if (!wis::succeeded(vr)) - return wis::make_result(vr); - } else { - version = VK_API_VERSION_1_0; - } - - wis::lib_info(wis::format("Vulkan version: {}.{}.{}", VK_API_VERSION_MAJOR(version), - VK_API_VERSION_MINOR(version), VK_API_VERSION_PATCH(version))); - - VkApplicationInfo info{ - VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr, "", VK_MAKE_API_VERSION(0, 1, 0, 0), "", - VK_MAKE_API_VERSION(0, 1, 0, 0), version - }; - - auto [res1, found_extensions] = VKFactory::FoundExtensions({ exts, exts + extension_count }); - if (res1.status != wis::Status::Ok) - return res1; - - auto [res2, found_layers] = VKFactory::FoundLayers({ layers, layers + layer_count }); - if (res2.status != wis::Status::Ok) - return res2; - - VkInstanceCreateInfo create_info{ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pApplicationInfo = &info, - .enabledLayerCount = uint32_t(found_layers.size), - .ppEnabledLayerNames = found_layers.get_data(), - .enabledExtensionCount = uint32_t(found_extensions.size), - .ppEnabledExtensionNames = found_extensions.get_data() }; - - VkInstance unsafe_instance; - vr = gt.vkCreateInstance(&create_info, nullptr, &unsafe_instance); - if (!wis::succeeded(vr)) - return wis::make_result(vr); - - return VKCreateFactoryEx(unsafe_instance, version, debug_layer); -} - -wis::ResultValue -wis::detail::VKCreateFactoryEx(VkInstance instance, uint32_t version, bool debug_layer) noexcept -{ - auto xr = detail::VKFactoryGlobals::Instance().InitializeFactoryGlobals(); - if (xr.status != wis::Status::Ok) - return xr; - - auto& gt = wis::detail::VKFactoryGlobals::GetGlobalTable(); - - auto destroy_instance = (PFN_vkDestroyInstance)gt.vkGetInstanceProcAddr(instance, "vkDestroyInstance"); - wis::managed_handle safe_instance{ instance, destroy_instance }; - auto table = wis::detail::make_unique(); - if (!table) - return wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); - - if (!table->Init(safe_instance.get(), gt.vkGetInstanceProcAddr)) - return wis::make_result(VK_ERROR_UNKNOWN); - - auto factory = wis::VKFactory{ wis::SharedInstance{ safe_instance.release(), destroy_instance, std::move(table), > }, version, debug_layer }; - auto result = factory.VKEnumeratePhysicalDevices(); - if (!wis::succeeded(result)) - return wis::make_result(result); - - return std::move(factory); -} #endif // !VK_CREATE_FACTORY_CPP diff --git a/wisdom/include/wisdom/vulkan/impl/vk_device.cpp b/wisdom/include/wisdom/vulkan/impl/vk_device.cpp index e157f0de..4bee0d64 100644 --- a/wisdom/include/wisdom/vulkan/impl/vk_device.cpp +++ b/wisdom/include/wisdom/vulkan/impl/vk_device.cpp @@ -83,28 +83,33 @@ GetQueueFamilies(VkPhysicalDevice adapter, const wis::VKMainInstance& itable) no return queues; } -inline static wis::ResultValue>> -GetAvailableExtensions(VkPhysicalDevice adapter, const wis::VKMainInstance& itable) +inline static std::unordered_map> +GetAvailableExtensions(wis::Result& result, VkPhysicalDevice adapter, const wis::VKMainInstance& itable) { std::unordered_map> ext_map; uint32_t count = 0; itable.vkEnumerateDeviceExtensionProperties(adapter, nullptr, &count, nullptr); wis::detail::fixed_allocation ext_props = wis::detail::make_fixed_allocation(count); - if (!ext_props) - return wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + if (!ext_props) { + result = wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + return ext_map; + } itable.vkEnumerateDeviceExtensionProperties(adapter, nullptr, &count, ext_props.get()); ext_map.reserve(count); - for (auto& ext : ext_props) + for (auto& ext : ext_props) { ext_map.emplace(ext.extensionName, ext); - + } return ext_map; } -wis::ResultValue -wis::ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts, uint32_t ext_size, bool force) noexcept +wis::VKDevice +wis::ImplVKCreateDevice(wis::Result& result, wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts, uint32_t ext_size, bool force) noexcept { + VKDevice out_device; + auto& internal = out_device.GetMutableInternal(); + auto& adapter_i = in_adapter.GetInternal(); auto hadapter = adapter_i.adapter; auto& itable = adapter_i.instance.table(); @@ -114,9 +119,10 @@ wis::ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts std::unordered_map struct_map; std::unordered_map property_map; std::unordered_set ext_name_set; - auto [res, available_exts] = GetAvailableExtensions(hadapter, itable); - if (res.status != wis::Status::Ok) - return res; + auto available_exts = GetAvailableExtensions(result, hadapter, itable); + if (result.status != wis::Status::Ok) { + return out_device; + } for (auto*& ext : exts_span) { bool supported = ext->GetExtensionInfo(available_exts, ext_name_set, struct_map, property_map); @@ -127,18 +133,22 @@ wis::ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts } // Ext1 - wis::VKDeviceExtensionEmbedded1 ext1; - if (!ext1.GetExtensionInfo(available_exts, ext_name_set, struct_map, property_map)) - return wis::make_result(VkResult::VK_ERROR_UNKNOWN); + if (!internal.ext1.GetExtensionInfo(available_exts, ext_name_set, struct_map, property_map)) { + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_device; + } // Allocate memory for extension names auto ext_names = wis::detail::make_fixed_allocation(ext_name_set.size()); - if (!ext_names) - return wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + if (!ext_names) { + result = wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + return out_device; + } size_t i = 0; - for (auto& ext : ext_name_set) + for (auto& ext : ext_name_set) { ext_names[i++] = ext.data(); + } // Initialize features VkPhysicalDeviceFeatures2 features{ @@ -160,13 +170,15 @@ wis::ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts // Allocate memory for all structures size_t allocation_size = 0; - for (auto& [type, size] : struct_map) + for (auto& [type, size] : struct_map) { allocation_size += size; + } auto allocation = wis::detail::make_fixed_allocation(allocation_size); - if (!allocation) - return wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); - + if (!allocation) { + result = wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + return out_device; + } memset(allocation.get_data(), 0, allocation_size); VkBaseInStructure* linked_struct = reinterpret_cast(&vulkan12_features); @@ -212,13 +224,15 @@ wis::ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts // Allocate memory for all properties allocation_size = 0; - for (auto& [type, size] : property_map) + for (auto& [type, size] : property_map) { allocation_size += size; + } auto allocation_props = wis::detail::make_fixed_allocation(allocation_size); - if (!allocation_props) - return wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); - + if (!allocation_props) { + result = wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + return out_device; + } memset(allocation_props.get_data(), 0, allocation_size); VkBaseInStructure* linked_prop = reinterpret_cast(&vulkan12_props); @@ -247,7 +261,7 @@ wis::ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts constexpr static auto max_queue_count = +wis::detail::QueueTypes::Count; wis::detail::uniform_allocator queue_infos{}; - auto queues = GetQueueFamilies(hadapter, itable); + internal.queues = GetQueueFamilies(hadapter, itable); constexpr static auto priorities = []() { std::array priorities{}; @@ -256,9 +270,10 @@ wis::ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts }(); for (size_t queue_info_size = 0; queue_info_size < max_queue_count; queue_info_size++) { - auto& q = queues.available_queues[queue_info_size]; - if (q.count == 0u) + auto& q = internal.queues.available_queues[queue_info_size]; + if (q.count == 0u) { continue; + } queue_infos.allocate() = { VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, nullptr, @@ -285,50 +300,53 @@ wis::ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts // Creating device VkDevice device; auto vres = itable.vkCreateDevice(hadapter, &device_info, nullptr, &device); - if (!wis::succeeded(vres)) - return wis::make_result(vres); - + if (!wis::succeeded(vres)) { + result = wis::make_result(vres); + return out_device; + } wis::managed_handle managed_device{ device, (PFN_vkDestroyDevice)gtable.vkGetDeviceProcAddr(device, "vkDestroyDevice") }; + std::unique_ptr device_table = wis::detail::make_unique(); - if (!device_table) - return wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + if (!device_table) { + result = wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + return out_device; + } - if (!device_table->Init(device, gtable.vkGetDeviceProcAddr)) - return wis::make_result(VkResult::VK_ERROR_UNKNOWN); + if (!device_table->Init(device, gtable.vkGetDeviceProcAddr)) { + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_device; + } - wis::VKDevice vkdevice{ wis::SharedDevice{ managed_device.release(), std::move(device_table), >able }, - std::move(in_adapter), std::move(ext1) }; + // Create the device + internal.adapter = std::move(in_adapter); + internal.device = wis::SharedDevice{ managed_device.release(), std::move(device_table), >able }; + internal.ext1.Init(out_device, struct_map, property_map); + if (!internal.ext1.Supported() && !force) { + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_device; + } - // Init embedded extensions - vkdevice.ext1.Init(vkdevice, struct_map, property_map); - if (!vkdevice.ext1.Supported() && !force) - return wis::make_result(VkResult::VK_ERROR_UNKNOWN); + // Init Default Layout + result = internal.InitDefaultLayout(); + if (result.status != wis::Status::Ok) { + return out_device; + } // Create Default Allocator - auto [res1, allocator] = vkdevice.VKCreateAllocator(); - if (res1.status != wis::Status::Ok) - return res1; - vkdevice.allocator = std::move(allocator); + internal.allocator = out_device.VKCreateAllocator(result); + if (result.status != wis::Status::Ok) { + return out_device; + } // Init the rest of the extensions for (auto*& ext : exts_span) { - if (ext == nullptr) + if (ext == nullptr) { continue; - ext->Init(vkdevice, struct_map, property_map); + } + ext->Init(out_device, struct_map, property_map); } - res1 = vkdevice.InitDefaultLayout(); - if (res1.status != wis::Status::Ok) - return res1; - - return { wis::success, std::move(vkdevice) }; -} - -wis::ImplVKDevice::ImplVKDevice(wis::SharedDevice in_device, wis::VKAdapter in_adapter, - wis::VKDeviceExtensionEmbedded1 ext1) noexcept - : QueryInternal(std::move(in_adapter), std::move(in_device), std::move(ext1)) -{ - queues = GetQueueFamilies(adapter.GetInternal().adapter, GetInstanceTable()); + return out_device; } wis::Result wis::ImplVKDevice::WaitForMultipleFences(const VKFenceView* fences, const uint64_t* values, @@ -348,9 +366,12 @@ wis::Result wis::ImplVKDevice::WaitForMultipleFences(const VKFenceView* fences, : wis::make_result(result); } -wis::ResultValue -wis::ImplVKDevice::CreateFence(uint64_t initial_value, wis::FenceFlags flags) const noexcept +wis::VKFence +wis::ImplVKDevice::CreateFence(wis::Result& result, uint64_t initial_value, wis::FenceFlags flags) const noexcept { + VKFence out_fence; + auto& internal = out_fence.GetMutableInternal(); + constexpr static VkExportSemaphoreCreateInfo export_info{ .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, .handleTypes = detail::semaphore_handle_type @@ -368,24 +389,26 @@ wis::ImplVKDevice::CreateFence(uint64_t initial_value, wis::FenceFlags flags) co .pNext = &timeline_desc, .flags = 0, }; - VkSemaphore sem; - VkResult result = device.table().vkCreateSemaphore(device.get(), &desc, nullptr, &sem); - if (!succeeded(result)) - return wis::make_result(result); + VkResult vr = device.table().vkCreateSemaphore(device.get(), &desc, nullptr, internal.fence.put(device, device.table().vkDestroySemaphore)); - return VKFence{ { sem, device, device.table().vkDestroySemaphore } }; + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_fence; + } + return out_fence; } -wis::ResultValue -wis::ImplVKDevice::CreateCommandQueue(wis::QueueType type) const noexcept +wis::VKCommandQueue +wis::ImplVKDevice::CreateCommandQueue(wis::Result& result, wis::QueueType type) const noexcept { + VKCommandQueue out_queue; + auto& internal = out_queue.GetMutableInternal(); const auto* queue = queues.GetOfType(type); - if (queue == nullptr) - return { wis::make_result( - VkResult::VK_ERROR_UNKNOWN), - wis::VKCommandQueue{} }; - + if (queue == nullptr) { + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_queue; + } VkDeviceQueueInfo2 info{ .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, .pNext = nullptr, @@ -393,9 +416,9 @@ wis::ImplVKDevice::CreateCommandQueue(wis::QueueType type) const noexcept .queueFamilyIndex = queue->family_index, .queueIndex = queue->GetNextInLine(), }; - VkQueue queue_handle; - device.table().vkGetDeviceQueue2(device.get(), &info, &queue_handle); - return wis::VKCommandQueue{ device, VkQueue{ queue_handle } }; + device.table().vkGetDeviceQueue2(device.get(), &info, &internal.queue); + internal.device = device; + return out_queue; } namespace wis::detail { @@ -404,8 +427,9 @@ inline void VKFillShaderStage(wis::detail::uniform_allocator(shader); - if (sh == nullptr) + if (sh == nullptr) { return; + } shader_stages.allocate() = { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, @@ -419,24 +443,29 @@ inline void VKFillShaderStage(wis::detail::uniform_allocator -wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* desc) const noexcept +wis::VKPipelineState +wis::ImplVKDevice::CreateGraphicsPipeline(wis::Result& result, const wis::VKGraphicsPipelineDesc& desc) const noexcept { + VKPipelineState out_pipeline; + auto& internal = out_pipeline.GetMutableInternal(); + wis::detail::uniform_allocator shader_stages; - wis::detail::VKFillShaderStage(shader_stages, desc->shaders.vertex, VK_SHADER_STAGE_VERTEX_BIT); - wis::detail::VKFillShaderStage(shader_stages, desc->shaders.pixel, VK_SHADER_STAGE_FRAGMENT_BIT); - wis::detail::VKFillShaderStage(shader_stages, desc->shaders.geometry, + wis::detail::VKFillShaderStage(shader_stages, desc.shaders.vertex, VK_SHADER_STAGE_VERTEX_BIT); + wis::detail::VKFillShaderStage(shader_stages, desc.shaders.pixel, VK_SHADER_STAGE_FRAGMENT_BIT); + wis::detail::VKFillShaderStage(shader_stages, desc.shaders.geometry, VK_SHADER_STAGE_GEOMETRY_BIT); - wis::detail::VKFillShaderStage(shader_stages, desc->shaders.hull, + wis::detail::VKFillShaderStage(shader_stages, desc.shaders.hull, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); - wis::detail::VKFillShaderStage(shader_stages, desc->shaders.domain, + wis::detail::VKFillShaderStage(shader_stages, desc.shaders.domain, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); - uint32_t ia_count = desc->input_layout.attribute_count; - if (ia_count > ext1.GetInternal().base_properties.max_ia_attributes) - return wis::make_result( + uint32_t ia_count = desc.input_layout.attribute_count; + if (ia_count > ext1.GetInternal().base_properties.max_ia_attributes) { + result = wis::make_result( VkResult::VK_ERROR_UNKNOWN); + return out_pipeline; + } wis::detail::limited_allocator attributes{ ia_count }; @@ -445,7 +474,7 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des auto* ia_data = attributes.data(); for (uint32_t i = 0; i < ia_count; i++) { auto& ia = ia_data[i]; - auto& a = desc->input_layout.attributes[i]; + auto& a = desc.input_layout.attributes[i]; ia.binding = a.input_slot; ia.format = convert_vk(a.format); ia.location = a.location; @@ -456,8 +485,8 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, - .vertexBindingDescriptionCount = desc->input_layout.slot_count, - .pVertexBindingDescriptions = desc->input_layout.slot_count ? reinterpret_cast(desc->input_layout.slots) : nullptr, + .vertexBindingDescriptionCount = desc.input_layout.slot_count, + .pVertexBindingDescriptions = desc.input_layout.slot_count ? reinterpret_cast(desc.input_layout.slots) : nullptr, .vertexAttributeDescriptionCount = ia_count, .pVertexAttributeDescriptions = ia_count ? ia_data : nullptr, }; @@ -490,20 +519,20 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des VkPipelineRasterizationStateCreateInfo rasterizer; - if (desc->rasterizer) { + if (desc.rasterizer) { rasterizer = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, - .depthClampEnable = desc->rasterizer->depth_clip_enable, + .depthClampEnable = desc.rasterizer->depth_clip_enable, .rasterizerDiscardEnable = false, - .polygonMode = convert_vk(desc->rasterizer->fill_mode), - .cullMode = convert_vk(desc->rasterizer->cull_mode), - .frontFace = convert_vk(desc->rasterizer->front_face), - .depthBiasEnable = desc->rasterizer->depth_bias_enable, - .depthBiasConstantFactor = desc->rasterizer->depth_bias, - .depthBiasClamp = desc->rasterizer->depth_bias_clamp, - .depthBiasSlopeFactor = desc->rasterizer->depth_bias_slope_factor, + .polygonMode = convert_vk(desc.rasterizer->fill_mode), + .cullMode = convert_vk(desc.rasterizer->cull_mode), + .frontFace = convert_vk(desc.rasterizer->front_face), + .depthBiasEnable = desc.rasterizer->depth_bias_enable, + .depthBiasConstantFactor = desc.rasterizer->depth_bias, + .depthBiasClamp = desc.rasterizer->depth_bias_clamp, + .depthBiasSlopeFactor = desc.rasterizer->depth_bias_slope_factor, .lineWidth = 1.0f, }; } @@ -512,24 +541,24 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, - .topology = convert_vk(desc->topology_type), + .topology = convert_vk(desc.topology_type), .primitiveRestartEnable = false, }; //--Render targets - uint32_t rt_size = std::min(desc->attachments.attachments_count, wis::max_render_targets); + uint32_t rt_size = std::min(desc.attachments.attachments_count, wis::max_render_targets); VkFormat rt_formats[8]{}; for (uint32_t i = 0; i < rt_size; i++) { - rt_formats[i] = convert_vk(desc->attachments.attachment_formats[i]); + rt_formats[i] = convert_vk(desc.attachments.attachment_formats[i]); } VkPipelineRenderingCreateInfo dynamic_rendering{ .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, .pNext = nullptr, - .viewMask = ext1.GetFeatures().multiview ? desc->view_mask : 0, + .viewMask = ext1.GetFeatures().multiview ? desc.view_mask : 0, .colorAttachmentCount = rt_size, .pColorAttachmentFormats = rt_formats, - .depthAttachmentFormat = convert_vk(desc->attachments.depth_attachment), + .depthAttachmentFormat = convert_vk(desc.attachments.depth_attachment), .stencilAttachmentFormat = VK_FORMAT_UNDEFINED // TODO: formats for pure stencils }; @@ -546,11 +575,12 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des }; VkPipelineColorBlendAttachmentState color_blend_attachment[max_render_targets]{}; VkPipelineColorBlendStateCreateInfo color_blending; - for (uint32_t i = 0; i < rt_size; i++) + for (uint32_t i = 0; i < rt_size; i++) { color_blend_attachment[i] = default_color_blend_attachment; + } - if (desc->blend) { - auto& blend = *desc->blend; + if (desc.blend) { + auto& blend = *desc.blend; if (!blend.logic_op_enable) { for (uint32_t i = 0; i < blend.attachment_count; i++) { auto& a = blend.attachments[i]; @@ -602,15 +632,15 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des }; VkPipelineMultisampleStateCreateInfo multisampling; - if (desc->sample) { + if (desc.sample) { multisampling = { .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, .pNext = nullptr, .flags = 0, - .rasterizationSamples = convert_vk(desc->sample->rate), + .rasterizationSamples = convert_vk(desc.sample->rate), .sampleShadingEnable = true, - .minSampleShading = desc->sample->quality, - .pSampleMask = &desc->sample->sample_mask, + .minSampleShading = desc.sample->quality, + .pSampleMask = &desc.sample->sample_mask, .alphaToCoverageEnable = false, .alphaToOneEnable = false, }; @@ -626,8 +656,8 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des }; VkPipelineDepthStencilStateCreateInfo depth_stencil_state; - if (desc->depth_stencil) { - auto& ds = *desc->depth_stencil; + if (desc.depth_stencil) { + auto& ds = *desc.depth_stencil; depth_stencil_state = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, .pNext = nullptr, @@ -668,11 +698,13 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des dynamic_state_enables.allocate(VkDynamicState::VK_DYNAMIC_STATE_SCISSOR); dynamic_state_enables.allocate(VkDynamicState::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY); - if (ia_count) + if (ia_count) { dynamic_state_enables.allocate(VkDynamicState::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE); + } - if (std::get<0>(desc->shaders.hull)) + if (std::get<0>(desc.shaders.hull)) { dynamic_state_enables.allocate(VkDynamicState::VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT); + } dynamic_state_enables.allocate(VkDynamicState::VK_DYNAMIC_STATE_BLEND_CONSTANTS); @@ -684,7 +716,7 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des .pDynamicStates = dynamic_state_enables.data() }; - VkPipelineCreateFlags flags = convert_vk(desc->flags); + VkPipelineCreateFlags flags = convert_vk(desc.flags); VkGraphicsPipelineCreateInfo info{ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, @@ -695,28 +727,28 @@ wis::ImplVKDevice::CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* des .pVertexInputState = &vertex_input, .pInputAssemblyState = &input_assembly, .pViewportState = &viewport_state, - .pRasterizationState = desc->rasterizer ? &rasterizer : &default_rasterizer, - .pMultisampleState = desc->sample ? &multisampling : &default_multisampling, - .pDepthStencilState = desc->depth_stencil ? &depth_stencil_state : &default_depth_stencil, + .pRasterizationState = desc.rasterizer ? &rasterizer : &default_rasterizer, + .pMultisampleState = desc.sample ? &multisampling : &default_multisampling, + .pDepthStencilState = desc.depth_stencil ? &depth_stencil_state : &default_depth_stencil, .pColorBlendState = &color_blending, .pDynamicState = &dynamic_state, - .layout = std::get<0>(desc->root_signature), + .layout = std::get<0>(desc.root_signature), }; - VkPipeline pipeline; - auto result = device.table().vkCreateGraphicsPipelines(device.get(), nullptr, 1u, &info, nullptr, - &pipeline); - if (!succeeded(result)) - return wis::make_result(result); - - return wis::VKPipelineState{ - wis::SharedPipeline{ pipeline, device, device.table().vkDestroyPipeline } - }; + auto vr = device.table().vkCreateGraphicsPipelines(device.get(), nullptr, 1u, &info, nullptr, + internal.pipeline.put_unsafe(device, device.table().vkDestroyPipeline)); + if (!succeeded(vr)) { + result = wis::make_result(vr); + } + return out_pipeline; } -wis::ResultValue -wis::ImplVKDevice::CreateCommandList(wis::QueueType type) const noexcept +wis::VKCommandList +wis::ImplVKDevice::CreateCommandList(wis::Result& result, wis::QueueType type) const noexcept { + VKCommandList out_list; + auto& internal = out_list.GetMutableInternal(); + auto& dtable = device.table(); VkCommandPoolCreateInfo cmd_pool_create_info{ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, @@ -725,10 +757,12 @@ wis::ImplVKDevice::CreateCommandList(wis::QueueType type) const noexcept .queueFamilyIndex = queues.GetOfType(type)->family_index, }; wis::scoped_handle cmd_pool; - auto result = + auto vr = dtable.vkCreateCommandPool(device.get(), &cmd_pool_create_info, nullptr, cmd_pool.put(device.get(), dtable.vkDestroyCommandPool)); - if (!succeeded(result)) - return wis::make_result(result); + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_list; + } VkCommandBufferAllocateInfo cmd_buf_alloc_info{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, @@ -738,11 +772,14 @@ wis::ImplVKDevice::CreateCommandList(wis::QueueType type) const noexcept .commandBufferCount = 1, }; - VkCommandBuffer cmd_buf; - result = dtable.vkAllocateCommandBuffers(device.get(), &cmd_buf_alloc_info, &cmd_buf); + vr = dtable.vkAllocateCommandBuffers(device.get(), &cmd_buf_alloc_info, &internal.command_list); + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_list; + } - if (!succeeded(result)) - return wis::make_result(result); + internal.device = device; + internal.allocator = cmd_pool.release(); VkCommandBufferBeginInfo desc{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -750,17 +787,20 @@ wis::ImplVKDevice::CreateCommandList(wis::QueueType type) const noexcept .flags = {}, .pInheritanceInfo = nullptr, }; - result = dtable.vkBeginCommandBuffer(cmd_buf, &desc); - if (!succeeded(result)) { - return make_result(result); + vr = dtable.vkBeginCommandBuffer(internal.command_list, &desc); + if (!succeeded(vr)) { + result = wis::make_result(vr); } - - return wis::VKCommandList{ device, cmd_pool.release(), cmd_buf }; + return out_list; } -wis::ResultValue wis::ImplVKDevice::CreateShader(void* bytecode, - uint32_t size) const noexcept +wis::VKShader +wis::ImplVKDevice::CreateShader(wis::Result& result, void* bytecode, + uint32_t size) const noexcept { + VKShader out_shader; + auto& internal = out_shader.GetMutableInternal(); + VkShaderModuleCreateInfo desc{ .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .pNext = nullptr, @@ -768,31 +808,33 @@ wis::ResultValue wis::ImplVKDevice::CreateShader(void* bytecode, .codeSize = size, .pCode = reinterpret_cast(bytecode), }; - VkShaderModule shader; - auto vr = device.table().vkCreateShaderModule(device.get(), &desc, nullptr, &shader); - - if (!succeeded(vr)) - return wis::make_result(vr); + auto vr = device.table().vkCreateShaderModule(device.get(), &desc, nullptr, internal.shader.put(device, device.table().vkDestroyShaderModule)); - return wis::VKShader{ wis::managed_handle_ex{ shader, device, device.table().vkDestroyShaderModule } }; + if (!succeeded(vr)) { + result = wis::make_result(vr); + } + return out_shader; } -wis::ResultValue wis::ImplVKDevice::CreateAllocator() const noexcept +wis::VKResourceAllocator +wis::ImplVKDevice::CreateAllocator(wis::Result& result) const noexcept { + VKResourceAllocator allocator; + auto& internal = allocator.GetMutableInternal(); + wis::shared_handle interop; if (ext1.GetFeatures().interop_device) { - auto [result, hallocator] = VKCreateAllocator(true); - if (result.status != wis::Status::Ok) - return result; - - interop = std::move(hallocator); + internal.export_memory_allocator = VKCreateAllocator(result, true); + if (result.status != wis::Status::Ok) { + return allocator; + } } - - return VKResourceAllocator{ allocator, std::move(interop) }; + internal.allocator = this->allocator; + return allocator; } -wis::ResultValue> -wis::ImplVKDevice::VKCreateAllocator(bool interop) const noexcept +wis::shared_handle +wis::ImplVKDevice::VKCreateAllocator(wis::Result& result, bool interop) const noexcept { uint32_t version = 0; auto& itable = GetInstanceTable(); @@ -851,8 +893,9 @@ wis::ImplVKDevice::VKCreateAllocator(bool interop) const noexcept .pTypeExternalMemoryHandleTypes = ext1.GetFeatures().interop_device && interop ? handle_types.data() : nullptr }; - if (ext1.GetFeatures().index_buffer_range) + if (ext1.GetFeatures().index_buffer_range) { allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_MAINTENANCE5_BIT; + } // Only if there is an interop extension if (ext1.GetFeatures().interop_device && interop) { @@ -862,90 +905,102 @@ wis::ImplVKDevice::VKCreateAllocator(bool interop) const noexcept #endif // WIN32 } - VmaAllocator al; - VkResult vr = vmaCreateAllocator(&allocatorInfo, &al); - - if (!succeeded(vr)) - return wis::make_result(vr); + wis::shared_handle out_allocator; + VkResult vr = vmaCreateAllocator(&allocatorInfo, out_allocator.put_unsafe(device)); - return wis::shared_handle{ device, al }; + if (!succeeded(vr)) { + result = wis::make_result(vr); + } + return out_allocator; } -wis::ResultValue -wis::ImplVKDevice::VKCreateSwapChain(wis::SharedSurface surface, +wis::VKSwapChain +wis::ImplVKDevice::VKCreateSwapChain(wis::Result& result, wis::SharedSurface surface, const SwapchainDesc* desc, VkQueue graphics_queue, void* pNext) const noexcept { + VKSwapChain out_swapchain; + auto& internal = out_swapchain.GetMutableInternal(); + auto& itable = GetInstanceTable(); auto& dtable = device.table(); auto hadapter = adapter.GetInternal().adapter; - int32_t present_queue = -1; - for (uint16_t i = 0; i < size_t(wis::detail::QueueTypes::Count); i++) { - const auto& x = queues.available_queues[i]; - if (x.Empty()) - continue; + // Get the surface capabilities and present queue + { + int32_t present_queue = -1; + auto hadapter = adapter.GetInternal().adapter; + for (uint16_t i = 0; i < size_t(wis::detail::QueueTypes::Count); i++) { + const auto& x = queues.available_queues[i]; + if (x.Empty()) { + continue; + } - VkBool32 supported = false; - auto result = itable.vkGetPhysicalDeviceSurfaceSupportKHR(hadapter, x.family_index, + VkBool32 supported = false; + auto vr = itable.vkGetPhysicalDeviceSurfaceSupportKHR(hadapter, x.family_index, surface.get(), &supported); - if (!succeeded(result)) - return wis::make_result( - result); - - if (supported) { - present_queue = i; - lib_info(format("Present queue {} selected", i)); - break; + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_swapchain; + } + + if (supported) { + present_queue = i; + break; + } } + if (present_queue == -1) { + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_swapchain; + } + const auto& queue = queues.available_queues[present_queue]; + VkDeviceQueueInfo2 info{ + .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, + .pNext = nullptr, + .flags = 0, + .queueFamilyIndex = queue.family_index, + .queueIndex = queue.GetNextInLine(), + }; + dtable.vkGetDeviceQueue2(device.get(), &info, &internal.present_queue); + internal.graphics_queue = graphics_queue; } - if (present_queue == -1) { - lib_error("None of the queues support presenting to the surface"); - return wis::make_result( - VkResult::VK_ERROR_UNKNOWN); - } - - const auto& queue = queues.available_queues[present_queue]; - VkDeviceQueueInfo2 info{ - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, - .pNext = nullptr, - .flags = 0, - .queueFamilyIndex = queue.family_index, - .queueIndex = queue.GetNextInLine(), - }; - VkQueue qpresent_queue; - dtable.vkGetDeviceQueue2(device.get(), &info, &qpresent_queue); uint32_t format_count = 0; itable.vkGetPhysicalDeviceSurfaceFormatsKHR(hadapter, surface.get(), &format_count, nullptr); wis::detail::fixed_allocation surface_formats = wis::detail::make_fixed_allocation(format_count); - auto result = itable.vkGetPhysicalDeviceSurfaceFormatsKHR(hadapter, surface.get(), - &format_count, surface_formats.get()); + if (!surface_formats) { + result = wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + return out_swapchain; + } + auto vr = itable.vkGetPhysicalDeviceSurfaceFormatsKHR(hadapter, surface.get(), + &format_count, surface_formats.get()); - if (!succeeded(result)) - return wis::make_result(result); + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_swapchain; + } auto format = std::ranges::find_if(surface_formats, [=](VkSurfaceFormatKHR fmt) { return fmt.format == convert_vk(desc->format); }); if (format == surface_formats.end() || format->format == VkFormat::VK_FORMAT_UNDEFINED) { - lib_error(wis::format("Supplied format {} is not supported by surface", +desc->format)); - return wis::make_result(VkResult::VK_ERROR_UNKNOWN); + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); // TODO: Make more meaningful error + return out_swapchain; } VkSurfaceCapabilitiesKHR cap{}; - - result = itable.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(hadapter, surface.get(), &cap); - if (!succeeded(result)) - return wis::make_result(result); - + vr = itable.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(hadapter, surface.get(), &cap); + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_swapchain; + } bool stereo = cap.maxImageArrayLayers > 1 && desc->stereo; - if (stereo) + if (stereo) { lib_info("Stereo mode is ativated"); + } uint32_t layers = stereo ? 2u : 1u; @@ -959,12 +1014,14 @@ wis::ImplVKDevice::VKCreateSwapChain(wis::SharedSurface surface, modes.data()); auto present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR; + bool tearing = desc->tearing; if (!desc->vsync) { if (desc->tearing) { - if (std::ranges::count(modes, VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR) > 0) + if (tearing = std::ranges::count(modes, VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR) > 0) { present_mode = VkPresentModeKHR::VK_PRESENT_MODE_IMMEDIATE_KHR; - else if (std::ranges::count(modes, VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR) > 0) + } else if (tearing = std::ranges::count(modes, VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR) > 0) { present_mode = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_RELAXED_KHR; + } } else if (std::ranges::count(modes, VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR) > 0 && !stereo) { present_mode = VkPresentModeKHR::VK_PRESENT_MODE_MAILBOX_KHR; } @@ -999,11 +1056,14 @@ wis::ImplVKDevice::VKCreateSwapChain(wis::SharedSurface surface, }; wis::scoped_handle swapchain; - result = dtable.vkCreateSwapchainKHR(device.get(), &swap_info, nullptr, swapchain.put(device.get(), dtable.vkDestroySwapchainKHR)); + vr = dtable.vkCreateSwapchainKHR(device.get(), &swap_info, nullptr, swapchain.put(device.get(), dtable.vkDestroySwapchainKHR)); - if (!succeeded(result)) - return wis::make_result(result); + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_swapchain; + } + // Create Command list VkCommandPoolCreateInfo cmd_pool_create_info{ .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, .pNext = nullptr, @@ -1011,9 +1071,11 @@ wis::ImplVKDevice::VKCreateSwapChain(wis::SharedSurface surface, .queueFamilyIndex = queues.GetOfType(wis::QueueType::Graphics)->family_index, }; wis::scoped_handle cmd_pool; - result = dtable.vkCreateCommandPool(device.get(), &cmd_pool_create_info, nullptr, cmd_pool.put(device.get(), dtable.vkDestroyCommandPool)); - if (!succeeded(result)) - return wis::make_result(result); + vr = dtable.vkCreateCommandPool(device.get(), &cmd_pool_create_info, nullptr, cmd_pool.put(device.get(), dtable.vkDestroyCommandPool)); + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_swapchain; + } VkCommandBufferAllocateInfo cmd_buf_alloc_info{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, @@ -1024,43 +1086,95 @@ wis::ImplVKDevice::VKCreateSwapChain(wis::SharedSurface surface, }; VkCommandBuffer cmd_buf; - result = dtable.vkAllocateCommandBuffers(device.get(), &cmd_buf_alloc_info, &cmd_buf); - if (!succeeded(result)) - return wis::make_result(result); - - wis::detail::VKSwapChainCreateInfo sci{ std::move(surface), - device, - adapter.GetInternal().adapter, - swapchain.release(), - cmd_buf, - cmd_pool.release(), - qpresent_queue, - graphics_queue, - *format, - present_mode, - ext1.GetFeatures().dynamic_vsync ? supported_presentation : uint8_t(0), - desc->tearing, - stereo, - desc->stereo }; - - auto rres = sci.InitBackBuffers(swap_info.imageExtent); - if (rres.status != wis::Status::Ok) - return rres; - - rres = sci.InitSemaphores(); - if (rres.status != wis::Status::Ok) - return rres; - - rres = sci.AcquireNextIndex(); - if (rres.status != wis::Status::Ok) - return rres; - - return wis::VKSwapChain{ std::move(sci) }; + vr = dtable.vkAllocateCommandBuffers(device.get(), &cmd_buf_alloc_info, &cmd_buf); + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_swapchain; + } + + // Create semaphores + internal.render_completed_semaphore = wis::detail::make_unique_for_overwrite(desc->buffer_count); + if (!internal.render_completed_semaphore) { + result = wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + return out_swapchain; + } + internal.image_ready_semaphores = wis::detail::make_unique_for_overwrite(desc->buffer_count); + if (!internal.image_ready_semaphores) { + result = wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + return out_swapchain; + } + constexpr VkSemaphoreCreateInfo semaphore_info{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; + for (uint32_t n = 0; n < desc->buffer_count; n++) { + vr = dtable.vkCreateSemaphore(device.get(), &semaphore_info, nullptr, &internal.render_completed_semaphore[n]); + if (!wis::succeeded(vr)) { + for (uint32_t i = 0; i < n; i++) { // Cleanup + dtable.vkDestroySemaphore(device.get(), internal.render_completed_semaphore[i], nullptr); + } + result = wis::make_result(vr); + return out_swapchain; + } + + vr = dtable.vkCreateSemaphore(device.get(), &semaphore_info, nullptr, &internal.image_ready_semaphores[n]); + if (!wis::succeeded(vr)) { + for (uint32_t i = 0; i < n; i++) { // Cleanup + dtable.vkDestroySemaphore(device.get(), internal.render_completed_semaphore[i], nullptr); + dtable.vkDestroySemaphore(device.get(), internal.image_ready_semaphores[i], nullptr); + } + result = wis::make_result(vr); + return out_swapchain; + } + } + + // Create fences + constexpr VkFenceCreateInfo fence_info{ .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; + for (uint32_t i = 0; i < internal.fences.size(); i++) { + vr = dtable.vkCreateFence(device.get(), &fence_info, nullptr, &internal.fences[i]); + if (!wis::succeeded(vr)) { + for (uint32_t i = 0; i < desc->buffer_count; i++) { // Cleanup (unless swapchain is set, the cleanup will not begin on internal) + dtable.vkDestroySemaphore(device.get(), internal.render_completed_semaphore[i], nullptr); + dtable.vkDestroySemaphore(device.get(), internal.image_ready_semaphores[i], nullptr); + } + for (uint32_t j = 0; j < i; j++) { + dtable.vkDestroyFence(device.get(), internal.fences[j], nullptr); + } + result = wis::make_result(vr); + return out_swapchain; + } + } + + internal.surface = std::move(surface); + internal.device = device; + internal.adapter = adapter.GetInternal().adapter; + internal.swapchain = swapchain.release(); + internal.initialization = cmd_buf; + internal.command_pool = cmd_pool.release(); + internal.format = *format; + internal.present_mode = present_mode; + internal.tearing = tearing; + internal.stereo = stereo; + internal.stereo_requested = desc->stereo; + + auto rres = internal.InitBackBuffers(swap_info.imageExtent); + if (rres.status != wis::Status::Ok) { + result = rres; + out_swapchain = {}; + return out_swapchain; + } + + rres = internal.AcquireNextIndex(); + if (rres.status != wis::Status::Ok) { + result = rres; + out_swapchain = {}; + } + return out_swapchain; } -wis::ResultValue -wis::ImplVKDevice::CreateRenderTarget(VKTextureView texture, wis::RenderTargetDesc desc) const noexcept +wis::VKRenderTarget +wis::ImplVKDevice::CreateRenderTarget(wis::Result& result, wis::VKTextureView texture, wis::RenderTargetDesc desc) const noexcept { + VKRenderTarget out_render_target; + auto& internal = out_render_target.GetMutableInternal(); + auto vk_format = convert_vk(desc.format); VkImageViewCreateInfo info{ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, @@ -1138,12 +1252,14 @@ wis::ImplVKDevice::CreateRenderTarget(VKTextureView texture, wis::RenderTargetDe break; } - VkImageView view; - auto result = device.table().vkCreateImageView(device.get(), &info, nullptr, &view); - if (!succeeded(result)) - return wis::make_result(result); + auto vr = device.table().vkCreateImageView(device.get(), &info, nullptr, internal.view.put(device, device.table().vkDestroyImageView)); + if (!succeeded(vr)) { + result = wis::make_result(vr); + return out_render_target; + } - return VKRenderTarget{ wis::managed_handle_ex{ view, device, device.table().vkDestroyImageView }, std::get<2>(texture) }; + internal.size = std::get<2>(texture); + return out_render_target; } bool wis::ImplVKDevice::QueryFeatureSupport(wis::DeviceFeature feature) const noexcept @@ -1170,49 +1286,55 @@ bool wis::ImplVKDevice::QueryFeatureSupport(wis::DeviceFeature feature) const no //-------------------------------------------------------------------------------------------------- -wis::ResultValue -wis::ImplVKDevice::CreateSampler(const wis::SamplerDesc* desc) const noexcept +wis::VKSampler +wis::ImplVKDevice::CreateSampler(wis::Result& result, const wis::SamplerDesc& desc) const noexcept { + VKSampler out_sampler; + auto& internal = out_sampler.GetMutableInternal(); + VkSamplerCustomBorderColorCreateInfoEXT custom_border_color{ .sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, .pNext = nullptr, .customBorderColor = { - desc->border_color[0], - desc->border_color[1], - desc->border_color[2], - desc->border_color[3], + desc.border_color[0], + desc.border_color[1], + desc.border_color[2], + desc.border_color[3], }, }; VkSamplerCreateInfo info{ .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, .pNext = &custom_border_color, .flags = 0, - .magFilter = convert_vk(desc->mag_filter), - .minFilter = convert_vk(desc->min_filter), - .mipmapMode = VkSamplerMipmapMode(desc->mip_filter), - .addressModeU = convert_vk(desc->address_u), - .addressModeV = convert_vk(desc->address_v), - .addressModeW = convert_vk(desc->address_w), - .mipLodBias = desc->mip_lod_bias, - .anisotropyEnable = desc->anisotropic, - .maxAnisotropy = float(desc->max_anisotropy), - .compareEnable = desc->comparison_op != wis::Compare::Never, - .compareOp = convert_vk(desc->comparison_op), - .minLod = desc->min_lod, - .maxLod = desc->max_lod, + .magFilter = convert_vk(desc.mag_filter), + .minFilter = convert_vk(desc.min_filter), + .mipmapMode = VkSamplerMipmapMode(desc.mip_filter), + .addressModeU = convert_vk(desc.address_u), + .addressModeV = convert_vk(desc.address_v), + .addressModeW = convert_vk(desc.address_w), + .mipLodBias = desc.mip_lod_bias, + .anisotropyEnable = desc.anisotropic, + .maxAnisotropy = float(desc.max_anisotropy), + .compareEnable = desc.comparison_op != wis::Compare::Never, + .compareOp = convert_vk(desc.comparison_op), + .minLod = desc.min_lod, + .maxLod = desc.max_lod, .borderColor = VkBorderColor::VK_BORDER_COLOR_FLOAT_CUSTOM_EXT }; - VkSampler sampler; - auto result = device.table().vkCreateSampler(device.get(), &info, nullptr, &sampler); - if (!succeeded(result)) - return wis::make_result(result); - return wis::VKSampler{ wis::managed_handle_ex{ sampler, device, device.table().vkDestroySampler } }; + auto vr = device.table().vkCreateSampler(device.get(), &info, nullptr, internal.sampler.put(device, device.table().vkDestroySampler)); + if (!succeeded(vr)) { + result = wis::make_result(vr); + } + return out_sampler; } -wis::ResultValue -wis::ImplVKDevice::CreateShaderResource(wis::VKTextureView texture, wis::ShaderResourceDesc desc) const noexcept +wis::VKShaderResource +wis::ImplVKDevice::CreateShaderResource(wis::Result& result, wis::VKTextureView texture, wis::ShaderResourceDesc desc) const noexcept { + VKShaderResource out_resource; + auto& internal = out_resource.GetMutableInternal(); + VkImageViewCreateInfo info{ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .pNext = nullptr, @@ -1278,17 +1400,19 @@ wis::ImplVKDevice::CreateShaderResource(wis::VKTextureView texture, wis::ShaderR break; } - VkImageView view; - auto res = device.table().vkCreateImageView(device.get(), &info, nullptr, &view); - if (!succeeded(res)) - return wis::make_result(res); - - return wis::VKShaderResource{ wis::managed_handle_ex{ view, device, device.table().vkDestroyImageView } }; + auto res = device.table().vkCreateImageView(device.get(), &info, nullptr, internal.view.put(device, device.table().vkDestroyImageView)); + if (!succeeded(res)) { + result = wis::make_result(res); + } + return out_resource; } -wis::ResultValue -wis::ImplVKDevice::CreateDescriptorStorage(wis::DescriptorStorageDesc desc) const noexcept +wis::VKDescriptorStorage +wis::ImplVKDevice::CreateDescriptorStorage(wis::Result& result, const wis::DescriptorStorageDesc& desc) const noexcept { + VKDescriptorStorage out_storage; + auto& internal = out_storage.GetMutableInternal(); + constexpr static uint32_t num_sets = Internal::max_sets; // Get max descriptor counts std::array desc_counts{ @@ -1320,6 +1444,10 @@ wis::ImplVKDevice::CreateDescriptorStorage(wis::DescriptorStorageDesc desc) cons }; wis::scoped_handle pool; auto res = device.table().vkCreateDescriptorPool(device.get(), &pool_info, nullptr, pool.put(device.get(), device.table().vkDestroyDescriptorPool)); + if (!succeeded(res)) { + result = wis::make_result(res); + return out_storage; + } VkDescriptorSetVariableDescriptorCountAllocateInfo variable_desc_info{ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, @@ -1328,42 +1456,51 @@ wis::ImplVKDevice::CreateDescriptorStorage(wis::DescriptorStorageDesc desc) cons .pDescriptorCounts = desc_counts.data(), }; - std::array desc_sets{}; VkDescriptorSetAllocateInfo desc_alloc_info{ .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, .pNext = &variable_desc_info, .descriptorPool = pool.get(), - .descriptorSetCount = std::size(desc_sets), + .descriptorSetCount = uint32_t(std::size(internal.set)), .pSetLayouts = default_layout.desc_sets.data(), }; - res = device.table().vkAllocateDescriptorSets(device.get(), &desc_alloc_info, desc_sets.data()); - if (!succeeded(res)) - return wis::make_result(res); - - return wis::VKDescriptorStorage{ device, pool.release(), std::move(desc_sets) }; + res = device.table().vkAllocateDescriptorSets(device.get(), &desc_alloc_info, internal.set.data()); + if (!succeeded(res)) { + result = wis::make_result(res); + return out_storage; + } + internal.pool = pool.release(); + internal.device = device; + return out_storage; } -wis::ResultValue -wis::ImplVKDevice::CreateRootSignature(const wis::PushConstant* constants, +wis::VKRootSignature +wis::ImplVKDevice::CreateRootSignature(wis::Result& result, const wis::PushConstant* constants, uint32_t constants_size, const PushDescriptor* push_descriptors, uint32_t push_descriptors_size, uint32_t space_overlap_count) const noexcept { + VKRootSignature out_signature; + auto& internal = out_signature.GetMutableInternal(); + constexpr static uint32_t num_sets = uint32_t(wis::BindingIndex::Count); if (constants_size > wis::max_push_constants) { - return wis::make_result(VkResult::VK_ERROR_UNKNOWN); + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_signature; } if (push_descriptors_size > wis::max_push_descriptors) { - return wis::make_result(VkResult::VK_ERROR_UNKNOWN); + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_signature; } if (space_overlap_count > wis::max_descriptor_space_overlap) { - return wis::make_result(VkResult::VK_ERROR_UNKNOWN); + result = wis::make_result(VkResult::VK_ERROR_UNKNOWN); + return out_signature; } - std::unique_ptr vk_dsl; - if (vk_dsl = wis::detail::make_unique_for_overwrite(num_sets + 1); !vk_dsl) - return wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + if (internal.vk_dsls = wis::detail::make_unique_for_overwrite(num_sets + 1); !internal.vk_dsls) { + result = wis::make_result(VkResult::VK_ERROR_OUT_OF_HOST_MEMORY); + return out_signature; + } // Create push descriptor set layout { @@ -1383,10 +1520,12 @@ wis::ImplVKDevice::CreateRootSignature(const wis::PushConstant* constants, .bindingCount = push_descriptors_size, .pBindings = push_bindings, }; - auto res = device.table().vkCreateDescriptorSetLayout(device.get(), &push_desc_info, nullptr, &vk_dsl[0]); - if (!succeeded(res)) - return wis::make_result(res); - std::copy_n(default_layout.desc_sets.begin(), num_sets, vk_dsl.get() + 1); + auto res = device.table().vkCreateDescriptorSetLayout(device.get(), &push_desc_info, nullptr, &internal.vk_dsls[0]); + if (!succeeded(res)) { + result = wis::make_result(res); + return out_signature; + } + std::copy_n(default_layout.desc_sets.begin(), num_sets, internal.vk_dsls.get() + 1); } VkPushConstantRange push_constants[wis::max_push_constants]{}; @@ -1403,28 +1542,26 @@ wis::ImplVKDevice::CreateRootSignature(const wis::PushConstant* constants, .pNext = nullptr, .flags = 0, .setLayoutCount = num_sets + 1, - .pSetLayouts = vk_dsl.get(), + .pSetLayouts = internal.vk_dsls.get(), .pushConstantRangeCount = constants_size, .pPushConstantRanges = push_constants, }; - VkPipelineLayout layout; - auto vr = device.table().vkCreatePipelineLayout(device.get(), &pipeline_layout_info, nullptr, &layout); - + auto vr = device.table().vkCreatePipelineLayout(device.get(), &pipeline_layout_info, nullptr, internal.root.put(device, device.table().vkDestroyPipelineLayout)); if (!succeeded(vr)) { - device.table().vkDestroyDescriptorSetLayout(device.get(), vk_dsl[0], nullptr); - return wis::make_result(vr); + device.table().vkDestroyDescriptorSetLayout(device.get(), internal.vk_dsls[0], nullptr); + result = wis::make_result(vr); } - - return VKRootSignature{ wis::managed_handle_ex{ layout, device, device.table().vkDestroyPipelineLayout }, std::move(vk_dsl), 1 }; + internal.dsl_count = 1; // number of descriptor set layouts to destroy + return out_signature; } -wis::ResultValue -wis::ImplVKDevice::CreateRootSignature2(const wis::PushConstant* push_constants, +wis::VKRootSignature +wis::ImplVKDevice::CreateRootSignature2(wis::Result& result, const wis::PushConstant* push_constants, uint32_t constants_count, const wis::PushDescriptor* push_descriptors, uint32_t push_descriptors_count, const wis::DescriptorSpacing* descriptor_spacing) const noexcept { - return CreateRootSignature(push_constants, constants_count, push_descriptors, push_descriptors_count, 1); + return CreateRootSignature(result, push_constants, constants_count, push_descriptors, push_descriptors_count, 1); } #endif diff --git a/wisdom/include/wisdom/vulkan/impl/vk_factory.cpp b/wisdom/include/wisdom/vulkan/impl/vk_factory.cpp index 06d04037..2c2ebb4c 100644 --- a/wisdom/include/wisdom/vulkan/impl/vk_factory.cpp +++ b/wisdom/include/wisdom/vulkan/impl/vk_factory.cpp @@ -43,24 +43,28 @@ inline constexpr uint32_t order_power(VkPhysicalDeviceType t) wis::Result VKFactoryGlobals::InitializeFactoryGlobals() noexcept { - if (initialized) + if (initialized) { return {}; + } wis::Result vr = {}; std::call_once( global_flag, [this, &vr]() { vr = InitializeGlobalTable(); - if (vr.status != wis::Status::Ok) + if (vr.status != wis::Status::Ok) { return; + } vr = InitializeInstanceExtensions(); - if (vr.status != wis::Status::Ok) + if (vr.status != wis::Status::Ok) { return; + } vr = InitializeInstanceLayers(); - if (vr.status != wis::Status::Ok) + if (vr.status != wis::Status::Ok) { return; + } }); initialized = true; @@ -69,8 +73,9 @@ wis::Result VKFactoryGlobals::InitializeFactoryGlobals() noexcept wis::Result VKFactoryGlobals::InitializeGlobalTable() noexcept { - if (!global_table.Init(lib_token)) + if (!global_table.Init(lib_token)) { return wis::make_result(VK_ERROR_INITIALIZATION_FAILED); + } return {}; } @@ -80,12 +85,14 @@ wis::Result VKFactoryGlobals::InitializeInstanceExtensions() noexcept uint32_t count = 0; gt.vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); auto extensions = wis::detail::make_fixed_allocation(count); - if (!extensions) + if (!extensions) { return wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + } auto vr = gt.vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions.get()); - if (!wis::succeeded(vr)) + if (!wis::succeeded(vr)) { return wis::make_result(vr); + } // may throw instance_extensions.reserve(count); @@ -100,12 +107,14 @@ wis::Result VKFactoryGlobals::InitializeInstanceLayers() noexcept uint32_t count = 0; gt.vkEnumerateInstanceLayerProperties(&count, nullptr); auto layers = wis::detail::make_fixed_allocation(count); - if (!layers) + if (!layers) { return wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + } auto vr = gt.vkEnumerateInstanceLayerProperties(&count, layers.get()); - if (!wis::succeeded(vr)) + if (!wis::succeeded(vr)) { return wis::make_result(vr); + } // may throw instance_layers.reserve(count); @@ -116,27 +125,26 @@ wis::Result VKFactoryGlobals::InitializeInstanceLayers() noexcept } } // namespace wis::detail -wis::ImplVKFactory::ImplVKFactory( - wis::SharedInstance instance, uint32_t api_ver, bool debug) noexcept - : QueryInternal(std::move(instance), api_ver, debug) +wis::VKAdapter +wis::ImplVKFactory::GetAdapter(wis::Result& result, uint32_t index, AdapterPreference preference) const noexcept { -} + VKAdapter out_adapter; + auto& internal = out_adapter.GetMutableInternal(); -wis::ResultValue -wis::ImplVKFactory::GetAdapter(uint32_t index, AdapterPreference preference) const noexcept -{ if (index >= adapters.size()) { - return wis::make_result(VK_ERROR_UNKNOWN); + result = wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY); + return out_adapter; } auto& adapter = adapters[index]; switch (preference) { default: - return adapter.adapter; + out_adapter = adapter.adapter; case AdapterPreference::MinConsumption: - return adapters[adapter.index_consumption].adapter; + out_adapter = adapters[adapter.index_consumption].adapter; case AdapterPreference::Performance: - return adapters[adapter.index_performance].adapter; + out_adapter = adapters[adapter.index_performance].adapter; } + return out_adapter; } VkResult wis::ImplVKFactory::VKEnumeratePhysicalDevices() noexcept @@ -146,12 +154,13 @@ VkResult wis::ImplVKFactory::VKEnumeratePhysicalDevices() noexcept std::vector phys_adapters; uint32_t count = 0; auto vr = factory.table().vkEnumeratePhysicalDevices(factory.get(), &count, nullptr); - do + do { phys_adapters.resize(count); - while ((vr = itable.vkEnumeratePhysicalDevices(factory.get(), &count, - phys_adapters.data())) == VK_INCOMPLETE); - if (!wis::succeeded(vr)) + } while ((vr = itable.vkEnumeratePhysicalDevices(factory.get(), &count, + phys_adapters.data())) == VK_INCOMPLETE); + if (!wis::succeeded(vr)) { return vr; + } adapters.resize(count); @@ -196,18 +205,20 @@ VkResult wis::ImplVKFactory::VKEnumeratePhysicalDevices() noexcept for (size_t i = 0; i < count; i++) { auto& adapter = adapters[i]; - adapter.adapter = VKAdapter{ - factory, phys_adapters[i] - }; + auto& internal = adapter.adapter.GetMutableInternal(); + + internal.instance = factory; + internal.adapter = phys_adapters[i]; adapter.index_performance = indices_perf[i]; adapter.index_consumption = indices_cons[i]; } } else { for (size_t i = 0; i < count; i++) { auto& adapter = adapters[i]; - adapter.adapter = VKAdapter{ - factory, phys_adapters[i] - }; + auto& internal = adapter.adapter.GetMutableInternal(); + + internal.instance = factory; + internal.adapter = phys_adapters[i]; adapter.index_performance = i; adapter.index_consumption = i; } diff --git a/wisdom/include/wisdom/vulkan/impl/vk_swapchain.cpp b/wisdom/include/wisdom/vulkan/impl/vk_swapchain.cpp index ebd0907b..65855485 100644 --- a/wisdom/include/wisdom/vulkan/impl/vk_swapchain.cpp +++ b/wisdom/include/wisdom/vulkan/impl/vk_swapchain.cpp @@ -10,28 +10,14 @@ wis::Result wis::detail::VKSwapChainCreateInfo::InitBackBuffers(VkExtent2D image_size) noexcept { auto& table = device.table(); - if (!fences[0]) { - VkFenceCreateInfo fence_info{ - .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - }; - auto result = table.vkCreateFence(device.get(), &fence_info, nullptr, &fences[0]); - if (!wis::succeeded(result)) - return { wis::make_result(result) }; - - result = table.vkCreateFence(device.get(), &fence_info, nullptr, &fences[1]); - if (!wis::succeeded(result)) - return { wis::make_result(result) }; - } - uint32_t new_back_buffer_count = 0; auto result = table.vkGetSwapchainImagesKHR(device.get(), swapchain, &new_back_buffer_count, nullptr); if (new_back_buffer_count > back_buffer_count) { back_buffers = wis::detail::make_unique_for_overwrite(new_back_buffer_count); - if (!back_buffers) + if (!back_buffers) { return { wis::make_result(result) }; + } back_buffer_count = new_back_buffer_count; } @@ -40,11 +26,15 @@ wis::Result wis::detail::VKSwapChainCreateInfo::InitBackBuffers(VkExtent2D image auto* image_data = allocator.data(); result = table.vkGetSwapchainImagesKHR(device.get(), swapchain, &new_back_buffer_count, image_data); - if (!wis::succeeded(result)) + if (!wis::succeeded(result)) { return { wis::make_result(result) }; + } for (uint32_t i = 0; i < back_buffer_count; ++i) { - back_buffers[i] = VKTexture{ format.format, image_data[i], { image_size.width, image_size.height } }; + auto& internal = back_buffers[i].GetMutableInternal(); + internal.buffer = image_data[i]; + internal.size = { image_size.width, image_size.height }; + internal.format = format.format; } result = table.vkResetCommandBuffer(initialization, 0); @@ -118,8 +108,9 @@ wis::Result wis::detail::VKSwapChainCreateInfo::AcquireNextIndex() const noexcep { auto& dtable = device.table(); auto result = dtable.vkAcquireNextImageKHR(device.get(), swapchain, std::numeric_limits::max(), image_ready_semaphores[acquire_index], nullptr, &present_index); - if (!wis::succeeded(result)) + if (!wis::succeeded(result)) { return wis::make_result(result); + } VkSemaphoreSubmitInfo submit_info{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, @@ -140,8 +131,9 @@ wis::Result wis::detail::VKSwapChainCreateInfo::AcquireNextIndexAndWait() const { auto& dtable = device.table(); auto result = dtable.vkAcquireNextImageKHR(device.get(), swapchain, std::numeric_limits::max(), image_ready_semaphores[acquire_index], nullptr, &present_index); - if (!wis::succeeded(result)) + if (!wis::succeeded(result)) { return wis::make_result(result); + } VkSemaphoreSubmitInfo submit_info{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO, @@ -166,8 +158,9 @@ wis::Result wis::detail::VKSwapChainCreateInfo::AcquireNextIndexAndWait() const wis::detail::VKSwapChainCreateInfo& wis::detail::VKSwapChainCreateInfo::operator=(VKSwapChainCreateInfo&& o) noexcept { - if (this == &o) + if (this == &o) { return *this; + } Destroy(); surface = std::move(o.surface); @@ -198,8 +191,9 @@ wis::detail::VKSwapChainCreateInfo& wis::detail::VKSwapChainCreateInfo::operator } void wis::detail::VKSwapChainCreateInfo::Destroy() noexcept { - if (!swapchain) + if (!swapchain) { return; + } auto& table = device.table(); auto hdevice = device.get(); @@ -216,34 +210,6 @@ void wis::detail::VKSwapChainCreateInfo::Destroy() noexcept table.vkDestroyCommandPool(hdevice, command_pool, nullptr); table.vkDestroySwapchainKHR(hdevice, swapchain, nullptr); } -wis::Result wis::detail::VKSwapChainCreateInfo::InitSemaphores() noexcept -{ - render_completed_semaphore = wis::detail::make_unique_for_overwrite(back_buffer_count); - if (!render_completed_semaphore) - return { wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY) }; - - image_ready_semaphores = wis::detail::make_unique_for_overwrite(back_buffer_count); - if (!image_ready_semaphores) - return { wis::make_result(VK_ERROR_OUT_OF_HOST_MEMORY) }; - - auto& table = device.table(); - VkSemaphoreCreateInfo semaphore_info{ - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - }; - - for (uint32_t n = 0; n < back_buffer_count; n++) { - auto result = table.vkCreateSemaphore(device.get(), &semaphore_info, nullptr, &render_completed_semaphore[n]); - if (!wis::succeeded(result)) - return { wis::make_result(result) }; - - auto result2 = table.vkCreateSemaphore(device.get(), &semaphore_info, nullptr, &image_ready_semaphores[n]); - if (!wis::succeeded(result2)) - return { wis::make_result(result) }; - } - return wis::success; -} void wis::detail::VKSwapChainCreateInfo::ReleaseSemaphores() noexcept { @@ -275,8 +241,9 @@ wis::Result wis::ImplVKSwapChain::WaitForPresent(uint64_t timeout_ns) const noexcept { auto& dtable = device.table(); - if (!dtable.vkWaitForPresentKHR) + if (!dtable.vkWaitForPresentKHR) { return wis::make_result(VK_ERROR_UNKNOWN); + } auto res = dtable.vkWaitForPresentKHR(device.get(), swapchain, present_id, timeout_ns); return wis::succeeded(res) ? wis::success : wis::make_result(res); @@ -327,8 +294,9 @@ wis::ImplVKSwapChain::VKRecreateSwapchain(uint32_t width, uint32_t height, void* dtable.vkDestroySwapchainKHR(device.get(), old_swapchain, nullptr); auto rres = InitBackBuffers(desc.imageExtent); - if (rres.status != wis::Status::Ok) + if (rres.status != wis::Status::Ok) { return rres; + } return AcquireNextIndexAndWait(); } diff --git a/wisdom/include/wisdom/vulkan/vk_adapter.h b/wisdom/include/wisdom/vulkan/vk_adapter.h index f8e5b3ce..e91a94a3 100644 --- a/wisdom/include/wisdom/vulkan/vk_adapter.h +++ b/wisdom/include/wisdom/vulkan/vk_adapter.h @@ -20,9 +20,6 @@ class ImplVKAdapter : public QueryInternal { public: ImplVKAdapter() noexcept = default; - explicit ImplVKAdapter(wis::SharedInstance instance, VkPhysicalDevice adapter) noexcept - : QueryInternal(std::move(instance), adapter) { } - operator bool() const noexcept { return adapter != nullptr; diff --git a/wisdom/include/wisdom/vulkan/vk_allocator.h b/wisdom/include/wisdom/vulkan/vk_allocator.h index 472ef041..74cfa764 100644 --- a/wisdom/include/wisdom/vulkan/vk_allocator.h +++ b/wisdom/include/wisdom/vulkan/vk_allocator.h @@ -17,11 +17,6 @@ class ImplVKResourceAllocator : public QueryInternal { public: ImplVKResourceAllocator() = default; - ImplVKResourceAllocator(wis::shared_handle allocator, - wis::shared_handle export_memory_allocator) noexcept - : QueryInternal(std::move(allocator), std::move(export_memory_allocator)) - { - } operator bool() const noexcept { return bool(allocator); @@ -29,11 +24,11 @@ class ImplVKResourceAllocator : public QueryInternal public: // Resource creation functions - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateBuffer(uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKBuffer + CreateBuffer(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateTexture(const wis::TextureDesc& desc, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKTexture + CreateTexture(wis::Result& result, const wis::TextureDesc& desc, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; // Allocation info functions [[nodiscard]] WIS_INLINE wis::AllocationInfo @@ -43,48 +38,48 @@ class ImplVKResourceAllocator : public QueryInternal GetBufferAllocationInfo(uint64_t size, wis::BufferUsage usage) const noexcept; // Allocation functions - [[nodiscard]] WIS_INLINE wis::ResultValue - AllocateTextureMemory(uint64_t size, wis::TextureUsage usage, + [[nodiscard]] WIS_INLINE wis::VKMemory + AllocateTextureMemory(wis::Result& result, uint64_t size, wis::TextureUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - AllocateBufferMemory(uint64_t size, wis::BufferUsage usage, + [[nodiscard]] WIS_INLINE wis::VKMemory + AllocateBufferMemory(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept; // Resource placement functions - [[nodiscard]] WIS_INLINE wis::ResultValue - PlaceBuffer(wis::VKMemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKBuffer + PlaceBuffer(wis::Result& result, wis::VKMemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - PlaceTexture(wis::VKMemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKTexture + PlaceTexture(wis::Result& result, wis::VKMemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept; public: // Convenience functions - [[nodiscard]] wis::ResultValue - CreateUploadBuffer(uint64_t size) const noexcept + [[nodiscard]] wis::VKBuffer + CreateUploadBuffer(wis::Result& result, uint64_t size) const noexcept { - return CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped); + return CreateBuffer(result, size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped); } - [[nodiscard]] wis::ResultValue - CreateReadbackBuffer(uint64_t size) const noexcept + [[nodiscard]] wis::VKBuffer + CreateReadbackBuffer(wis::Result& result, uint64_t size) const noexcept { - return CreateBuffer(size, BufferUsage::CopyDst, MemoryType::Readback, wis::MemoryFlags::Mapped); + return CreateBuffer(result, size, BufferUsage::CopyDst, MemoryType::Readback, wis::MemoryFlags::Mapped); } public: - [[nodiscard]] WIS_INLINE wis::ResultValue - VKCreateBuffer(VkBufferCreateInfo& desc, const VmaAllocationCreateInfo& alloc_desc, bool interop = false) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKBuffer + VKCreateBuffer(wis::Result& result, VkBufferCreateInfo& desc, const VmaAllocationCreateInfo& alloc_desc, bool interop = false) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - VKCreateTexture(VkImageCreateInfo& desc, const VmaAllocationCreateInfo& alloc_desc, bool interop = false) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKTexture + VKCreateTexture(wis::Result& result, VkImageCreateInfo& desc, const VmaAllocationCreateInfo& alloc_desc, bool interop = false) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - VKCreateAliasingBuffer(VkBufferCreateInfo& desc, VkDeviceSize offset, VmaAllocation alloc, bool interop = false) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKBuffer + VKCreateAliasingBuffer(wis::Result& result, VkBufferCreateInfo& desc, VkDeviceSize offset, VmaAllocation alloc, bool interop = false) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - VKCreateAliasingTexture(VkImageCreateInfo& desc, VkDeviceSize offset, VmaAllocation alloc, bool interop = false) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKTexture + VKCreateAliasingTexture(wis::Result& result, VkImageCreateInfo& desc, VkDeviceSize offset, VmaAllocation alloc, bool interop = false) const noexcept; WIS_INLINE static void VKFillBufferDesc(uint64_t size, BufferUsage flags, VkBufferCreateInfo& info) noexcept; @@ -110,6 +105,19 @@ class VKResourceAllocator : public wis::ImplVKResourceAllocator using wis::ImplVKResourceAllocator::ImplVKResourceAllocator; public: + /** + * @brief Creates a buffer object and allocates memory for it. + * Equivalent to creating a Buffer, allocating a memory and binding buffer to it. + * @param size The size of the buffer in bytes. + * @param usage The usage of the buffer. May affect the alignment of the buffer memory allocation. + * @param memory The type of the memory to allocate for the buffer. + * @param mem_flags The flags of the memory to allocate for the buffer. + * @return wis::VKBuffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKBuffer CreateBuffer(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplVKResourceAllocator::CreateBuffer(result, size, usage, memory, mem_flags); + } /** * @brief Creates a buffer object and allocates memory for it. * Equivalent to creating a Buffer, allocating a memory and binding buffer to it. @@ -121,7 +129,19 @@ class VKResourceAllocator : public wis::ImplVKResourceAllocator * */ [[nodiscard]] inline wis::ResultValue CreateBuffer(uint64_t size, wis::BufferUsage usage, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept { - return wis::ImplVKResourceAllocator::CreateBuffer(size, usage, memory, mem_flags); + return wis::ResultValue{ &wis::ImplVKResourceAllocator::CreateBuffer, this, size, usage, memory, mem_flags }; + } + /** + * @brief Creates a texture object and allocates memory for it. + * Equivalent to creating a Texture, allocating a memory and binding texture to it. + * @param desc The description of the texture to create. + * @param memory The type of the memory to allocate for the texture. + * @param mem_flags The flags of the memory to allocate for the texture. + * @return wis::VKTexture on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKTexture CreateTexture(wis::Result& result, const wis::TextureDesc& desc, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplVKResourceAllocator::CreateTexture(result, desc, memory, mem_flags); } /** * @brief Creates a texture object and allocates memory for it. @@ -133,7 +153,47 @@ class VKResourceAllocator : public wis::ImplVKResourceAllocator * */ [[nodiscard]] inline wis::ResultValue CreateTexture(const wis::TextureDesc& desc, wis::MemoryType memory = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept { - return wis::ImplVKResourceAllocator::CreateTexture(desc, memory, mem_flags); + return wis::ResultValue{ &wis::ImplVKResourceAllocator::CreateTexture, this, desc, memory, mem_flags }; + } + /** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param size The size of the buffer in bytes. + * @return wis::VKBuffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKBuffer CreateUploadBuffer(wis::Result& result, uint64_t size) const noexcept + { + return wis::ImplVKResourceAllocator::CreateUploadBuffer(result, size); + } + /** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param size The size of the buffer in bytes. + * @return wis::VKBuffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateUploadBuffer(uint64_t size) const noexcept + { + return wis::ResultValue{ &wis::ImplVKResourceAllocator::CreateUploadBuffer, this, size }; + } + /** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param size The size of the buffer in bytes. + * @return wis::VKBuffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKBuffer CreateReadbackBuffer(wis::Result& result, uint64_t size) const noexcept + { + return wis::ImplVKResourceAllocator::CreateReadbackBuffer(result, size); + } + /** + * @brief Convenience function for creating a buffer object and allocating memory for it. + * Equivalent to calling CreateBuffer(size, BufferUsage::CopySrc, MemoryType::Upload, wis::MemoryFlags::Mapped) + * @param size The size of the buffer in bytes. + * @return wis::VKBuffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateReadbackBuffer(uint64_t size) const noexcept + { + return wis::ResultValue{ &wis::ImplVKResourceAllocator::CreateReadbackBuffer, this, size }; } /** * @brief Returns the allocation info for the texture. @@ -154,6 +214,18 @@ class VKResourceAllocator : public wis::ImplVKResourceAllocator { return wis::ImplVKResourceAllocator::GetBufferAllocationInfo(size, usage); } + /** + * @brief Allocates memory for the image. + * @param size The size of the memory to allocate. + * @param usage The usage of the image memory. + * @param mem_type The type of the memory to allocate for the image. + * @param mem_flags The flags of the memory to allocate for the image. + * @return wis::VKMemory on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKMemory AllocateTextureMemory(wis::Result& result, uint64_t size, wis::TextureUsage usage, wis::MemoryType mem_type = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplVKResourceAllocator::AllocateTextureMemory(result, size, usage, mem_type, mem_flags); + } /** * @brief Allocates memory for the image. * @param size The size of the memory to allocate. @@ -164,7 +236,19 @@ class VKResourceAllocator : public wis::ImplVKResourceAllocator * */ [[nodiscard]] inline wis::ResultValue AllocateTextureMemory(uint64_t size, wis::TextureUsage usage, wis::MemoryType mem_type = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept { - return wis::ImplVKResourceAllocator::AllocateTextureMemory(size, usage, mem_type, mem_flags); + return wis::ResultValue{ &wis::ImplVKResourceAllocator::AllocateTextureMemory, this, size, usage, mem_type, mem_flags }; + } + /** + * @brief Allocates memory for the buffer. + * @param size The size of the memory to allocate. + * @param usage The usage of the buffer memory. + * @param mem_type The type of the memory to allocate for the buffer. + * @param mem_flags The flags of the memory to allocate for the buffer. + * @return wis::VKMemory on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKMemory AllocateBufferMemory(wis::Result& result, uint64_t size, wis::BufferUsage usage, wis::MemoryType mem_type = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept + { + return wis::ImplVKResourceAllocator::AllocateBufferMemory(result, size, usage, mem_type, mem_flags); } /** * @brief Allocates memory for the buffer. @@ -176,7 +260,21 @@ class VKResourceAllocator : public wis::ImplVKResourceAllocator * */ [[nodiscard]] inline wis::ResultValue AllocateBufferMemory(uint64_t size, wis::BufferUsage usage, wis::MemoryType mem_type = wis::MemoryType::Default, wis::MemoryFlags mem_flags = wis::MemoryFlags::None) const noexcept { - return wis::ImplVKResourceAllocator::AllocateBufferMemory(size, usage, mem_type, mem_flags); + return wis::ResultValue{ &wis::ImplVKResourceAllocator::AllocateBufferMemory, this, size, usage, mem_type, mem_flags }; + } + /** + * @brief Creates buffer with provided memory. + * Equivalent to creating aliasing resource. + * Note, the resulting buffer must be destroyed before Memory backing it up. + * @param memory The memory to bind the buffer to. + * @param memory_offset The offset in the memory to bind the buffer to. + * @param size The size of the buffer to bind. + * @param usage The usage of the buffer. + * @return wis::VKBuffer on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKBuffer PlaceBuffer(wis::Result& result, wis::VKMemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept + { + return wis::ImplVKResourceAllocator::PlaceBuffer(result, std::move(memory), memory_offset, size, usage); } /** * @brief Creates buffer with provided memory. @@ -190,7 +288,20 @@ class VKResourceAllocator : public wis::ImplVKResourceAllocator * */ [[nodiscard]] inline wis::ResultValue PlaceBuffer(wis::VKMemoryView memory, uint64_t memory_offset, uint64_t size, wis::BufferUsage usage) const noexcept { - return wis::ImplVKResourceAllocator::PlaceBuffer(std::move(memory), memory_offset, size, usage); + return wis::ResultValue{ &wis::ImplVKResourceAllocator::PlaceBuffer, this, std::move(memory), memory_offset, size, usage }; + } + /** + * @brief Creates texture with provided memory. + * Equivalent to creating aliasing resource. + * Note, the resulting Texture must be destroyed before Memory backing it up. + * @param memory The memory to bind the buffer to. + * @param memory_offset The offset in the memory to bind the texture to. + * @param desc The description of the texture to create. + * @return wis::VKTexture on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKTexture PlaceTexture(wis::Result& result, wis::VKMemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept + { + return wis::ImplVKResourceAllocator::PlaceTexture(result, std::move(memory), memory_offset, desc); } /** * @brief Creates texture with provided memory. @@ -203,7 +314,7 @@ class VKResourceAllocator : public wis::ImplVKResourceAllocator * */ [[nodiscard]] inline wis::ResultValue PlaceTexture(wis::VKMemoryView memory, uint64_t memory_offset, const wis::TextureDesc& desc) const noexcept { - return wis::ImplVKResourceAllocator::PlaceTexture(std::move(memory), memory_offset, desc); + return wis::ResultValue{ &wis::ImplVKResourceAllocator::PlaceTexture, this, std::move(memory), memory_offset, desc }; } }; #pragma endregion VKResourceAllocator diff --git a/wisdom/include/wisdom/vulkan/vk_command_list.h b/wisdom/include/wisdom/vulkan/vk_command_list.h index fab12dc3..776181ab 100644 --- a/wisdom/include/wisdom/vulkan/vk_command_list.h +++ b/wisdom/include/wisdom/vulkan/vk_command_list.h @@ -1,6 +1,6 @@ #ifndef WIS_VK_COMMAND_LIST_H #define WIS_VK_COMMAND_LIST_H -#include +#include #include #include #include @@ -24,9 +24,6 @@ struct Internal { public: Internal() noexcept = default; - Internal(wis::SharedDevice device, VkCommandPool allocator, VkCommandBuffer command_list) noexcept - : device(std::move(device)), allocator(allocator), command_list(command_list) { } - Internal(Internal&&) noexcept = default; Internal& operator=(Internal&& o) noexcept { @@ -59,9 +56,6 @@ class ImplVKCommandList : public QueryInternal { public: ImplVKCommandList() noexcept = default; - explicit ImplVKCommandList(wis::SharedDevice device, VkCommandPool allocator, VkCommandBuffer command_list) noexcept - : QueryInternal(std::move(device), allocator, command_list) { } - operator bool() const noexcept { return bool(command_list); @@ -183,7 +177,7 @@ class VKCommandList : public wis::ImplVKCommandList * @param destination The destination buffer to copy to. * @param region The region to copy. * */ - inline void CopyBuffer(wis::VKBufferView source, wis::VKBufferView destination, wis::BufferRegion region) noexcept + inline void CopyBuffer(wis::VKBufferView source, wis::VKBufferView destination, const wis::BufferRegion& region) noexcept { wis::ImplVKCommandList::CopyBuffer(std::move(source), std::move(destination), region); } @@ -214,7 +208,7 @@ class VKCommandList : public wis::ImplVKCommandList * @param barrier The barrier to set. * @param buffer The buffer to set the barrier on. * */ - inline void BufferBarrier(wis::BufferBarrier barrier, wis::VKBufferView buffer) noexcept + inline void BufferBarrier(const wis::BufferBarrier& barrier, wis::VKBufferView buffer) noexcept { wis::ImplVKCommandList::BufferBarrier(barrier, std::move(buffer)); } @@ -232,7 +226,7 @@ class VKCommandList : public wis::ImplVKCommandList * @param barrier The barrier to set. * @param texture The texture to set the barrier on. * */ - inline void TextureBarrier(wis::TextureBarrier barrier, wis::VKTextureView texture) noexcept + inline void TextureBarrier(const wis::TextureBarrier& barrier, wis::VKTextureView texture) noexcept { wis::ImplVKCommandList::TextureBarrier(barrier, std::move(texture)); } @@ -313,7 +307,7 @@ class VKCommandList : public wis::ImplVKCommandList * @brief Sets the viewport. * @param viewport The viewport to set. * */ - inline void RSSetViewport(wis::Viewport viewport) noexcept + inline void RSSetViewport(const wis::Viewport& viewport) noexcept { wis::ImplVKCommandList::RSSetViewport(viewport); } @@ -330,7 +324,7 @@ class VKCommandList : public wis::ImplVKCommandList * @brief Sets the scissor rect. * @param scissor The scissor to set. * */ - inline void RSSetScissor(wis::Scissor scissor) noexcept + inline void RSSetScissor(const wis::Scissor& scissor) noexcept { wis::ImplVKCommandList::RSSetScissor(scissor); } diff --git a/wisdom/include/wisdom/vulkan/vk_command_queue.h b/wisdom/include/wisdom/vulkan/vk_command_queue.h index ab5ac26d..dace6b20 100644 --- a/wisdom/include/wisdom/vulkan/vk_command_queue.h +++ b/wisdom/include/wisdom/vulkan/vk_command_queue.h @@ -15,9 +15,6 @@ struct Internal { public: Internal() noexcept = default; ~Internal() noexcept = default; - Internal(wis::SharedDevice device, VkQueue queue) noexcept - : device(std::move(device)), queue(queue) { } - Internal(Internal&&) noexcept = default; Internal& operator=(Internal&& o) noexcept { @@ -36,9 +33,6 @@ class ImplVKCommandQueue : public QueryInternal { public: ImplVKCommandQueue() = default; - explicit ImplVKCommandQueue(wis::SharedDevice device, VkQueue queue) - : QueryInternal(std::move(device), queue) { } - operator bool() const noexcept { return bool(queue); diff --git a/wisdom/include/wisdom/vulkan/vk_convert.h b/wisdom/include/wisdom/vulkan/vk_convert.h index 21ba7936..893653b8 100644 --- a/wisdom/include/wisdom/vulkan/vk_convert.h +++ b/wisdom/include/wisdom/vulkan/vk_convert.h @@ -1,7 +1,7 @@ #ifndef WIS_VK_CONVERT_H #define WIS_VK_CONVERT_H #include -#include +#include namespace wis { inline constexpr wis::Status convert_vk(VkResult hr) noexcept diff --git a/wisdom/include/wisdom/vulkan/vk_debug.h b/wisdom/include/wisdom/vulkan/vk_debug.h index c8745dc1..19b85140 100644 --- a/wisdom/include/wisdom/vulkan/vk_debug.h +++ b/wisdom/include/wisdom/vulkan/vk_debug.h @@ -22,10 +22,6 @@ struct Internal { public: Internal() noexcept = default; - Internal(wis::SharedInstance instance, VkDebugUtilsMessengerEXT messenger, std::unique_ptr data, PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT) noexcept - : instance(std::move(instance)), messenger(messenger), data(std::move(data)), vkDestroyDebugUtilsMessengerEXT(vkDestroyDebugUtilsMessengerEXT) - { - } Internal(Internal&&) noexcept = default; Internal& operator=(Internal&& other) noexcept { @@ -47,8 +43,9 @@ struct Internal { void Destroy() noexcept { - if (messenger) + if (messenger) { vkDestroyDebugUtilsMessengerEXT(instance.get(), messenger, nullptr); + } messenger = nullptr; } }; @@ -57,10 +54,6 @@ class VKDebugMessenger : public QueryInternal { public: VKDebugMessenger() noexcept = default; - explicit VKDebugMessenger(wis::SharedInstance instance, VkDebugUtilsMessengerEXT messenger, std::unique_ptr data, PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT) noexcept - : QueryInternal(std::move(instance), messenger, std::move(data), vkDestroyDebugUtilsMessengerEXT) - { - } operator bool() const noexcept { return bool(messenger); diff --git a/wisdom/include/wisdom/vulkan/vk_descriptor_storage.h b/wisdom/include/wisdom/vulkan/vk_descriptor_storage.h index fdf42cb0..5a9f429c 100644 --- a/wisdom/include/wisdom/vulkan/vk_descriptor_storage.h +++ b/wisdom/include/wisdom/vulkan/vk_descriptor_storage.h @@ -18,8 +18,6 @@ struct Internal { public: Internal() noexcept = default; - Internal(wis::SharedDevice device, VkDescriptorPool pool, std::array set) noexcept - : device(std::move(device)), pool(pool), set(std::move(set)) { } Internal(Internal&&) noexcept = default; Internal& operator=(Internal&& o) noexcept { @@ -50,9 +48,6 @@ class ImplVKDescriptorStorage : public QueryInternal { public: ImplVKDescriptorStorage() noexcept = default; - explicit ImplVKDescriptorStorage(wis::SharedDevice device, VkDescriptorPool pool, std::array set) noexcept - : QueryInternal(std::move(device), pool, std::move(set)) { } - operator bool() const noexcept { return bool(pool); diff --git a/wisdom/include/wisdom/vulkan/vk_device.h b/wisdom/include/wisdom/vulkan/vk_device.h index 9b386267..d4d0ac83 100644 --- a/wisdom/include/wisdom/vulkan/vk_device.h +++ b/wisdom/include/wisdom/vulkan/vk_device.h @@ -105,8 +105,9 @@ struct Internal { } for (size_t i = 0; i < num_sets; i++) { auto res = vkCreateDescriptorSetLayout(device, &desc_info[i], nullptr, &desc_sets[i]); - if (!succeeded(res)) + if (!succeeded(res)) { return wis::make_result(res); + } } return wis::success; } @@ -114,10 +115,6 @@ struct Internal { public: Internal() noexcept = default; - Internal(wis::VKAdapter adapter, wis::SharedDevice device, wis::VKDeviceExtensionEmbedded1 ext1) noexcept - : adapter(std::move(adapter)), device(std::move(device)), ext1(std::move(ext1)) - { - } Internal(Internal&&) noexcept = default; Internal& operator=(Internal&& o) noexcept { @@ -139,7 +136,7 @@ struct Internal { } ~Internal() noexcept { - if (device.get()) { + if (device.get() && default_layout.Valid()) { default_layout.Destroy(device.table().vkDestroyDescriptorSetLayout, device.get()); } } @@ -173,15 +170,11 @@ struct Internal { class ImplVKDevice : public QueryInternal { - friend wis::ResultValue - ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts, uint32_t ext_size, bool force) noexcept; + friend wis::VKDevice + ImplVKCreateDevice(wis::Result& result, wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts, uint32_t ext_size, bool force) noexcept; public: ImplVKDevice() noexcept = default; - WIS_INLINE explicit ImplVKDevice(wis::SharedDevice device, - wis::VKAdapter adapter, - wis::VKDeviceExtensionEmbedded1 ext1) noexcept; - operator bool() const noexcept { return bool(device); @@ -199,66 +192,66 @@ class ImplVKDevice : public QueryInternal MutiWaitFlags wait_all = MutiWaitFlags::All, uint64_t timeout = std::numeric_limits::max()) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateFence(uint64_t initial_value = 0ull, wis::FenceFlags flags = wis::FenceFlags::None) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKFence + CreateFence(wis::Result& result, uint64_t initial_value = 0ull, wis::FenceFlags flags = wis::FenceFlags::None) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateCommandQueue(wis::QueueType type) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKCommandQueue + CreateCommandQueue(wis::Result& result, wis::QueueType type) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateCommandList(wis::QueueType type) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKCommandList + CreateCommandList(wis::Result& result, wis::QueueType type) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKPipelineState + CreateGraphicsPipeline(wis::Result& result, const wis::VKGraphicsPipelineDesc& desc) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateShader(void* bytecode, uint32_t size) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKShader + CreateShader(wis::Result& result, void* bytecode, uint32_t size) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateAllocator() const noexcept; + [[nodiscard]] WIS_INLINE wis::VKResourceAllocator + CreateAllocator(wis::Result& result) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateRenderTarget(VKTextureView texture, wis::RenderTargetDesc desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKRenderTarget + CreateRenderTarget(wis::Result& result, VKTextureView texture, wis::RenderTargetDesc desc) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateDepthStencilTarget(VKTextureView texture, wis::RenderTargetDesc desc) const noexcept + [[nodiscard]] WIS_INLINE wis::VKRenderTarget + CreateDepthStencilTarget(wis::Result& result, VKTextureView texture, wis::RenderTargetDesc desc) const noexcept { - return CreateRenderTarget(texture, desc); + return CreateRenderTarget(result, texture, desc); } - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateSampler(const wis::SamplerDesc* desc) const noexcept; + [[nodiscard]] WIS_INLINE VKSampler + CreateSampler(wis::Result& result, const wis::SamplerDesc& desc) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateShaderResource(VKTextureView texture, wis::ShaderResourceDesc desc) const noexcept; + [[nodiscard]] WIS_INLINE VKShaderResource + CreateShaderResource(wis::Result& result, VKTextureView texture, wis::ShaderResourceDesc desc) const noexcept; [[nodiscard]] WIS_INLINE bool QueryFeatureSupport(wis::DeviceFeature feature) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateDescriptorStorage(wis::DescriptorStorageDesc desc) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKDescriptorStorage + CreateDescriptorStorage(wis::Result& result, const wis::DescriptorStorageDesc& desc) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateRootSignature(const PushConstant* constants = nullptr, + [[nodiscard]] WIS_INLINE wis::VKRootSignature + CreateRootSignature(wis::Result& result, const PushConstant* constants = nullptr, uint32_t constants_size = 0, const PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_size = 0, [[maybe_unused]] uint32_t space_overlap_count = 1) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateRootSignature2(const wis::PushConstant* push_constants = nullptr, + [[nodiscard]] WIS_INLINE wis::VKRootSignature + CreateRootSignature2(wis::Result& result, const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_count = 0, const wis::DescriptorSpacing* descriptor_spacing = nullptr) const noexcept; public: - [[nodiscard]] WIS_INLINE wis::ResultValue - VKCreateSwapChain(wis::SharedSurface surface, const SwapchainDesc* desc, VkQueue graphics_queue, void* pNext = nullptr) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKSwapChain + VKCreateSwapChain(wis::Result& result, wis::SharedSurface surface, const SwapchainDesc* desc, VkQueue graphics_queue, void* pNext = nullptr) const noexcept; protected: - [[nodiscard]] WIS_INLINE wis::ResultValue> - VKCreateAllocator(bool interop = false) const noexcept; + [[nodiscard]] WIS_INLINE wis::shared_handle + VKCreateAllocator(wis::Result& result, bool interop = false) const noexcept; }; #pragma region VKDevice @@ -290,6 +283,16 @@ class VKDevice : public wis::ImplVKDevice { return wis::ImplVKDevice::WaitForMultipleFences(fences, fence_values, fence_count, wait_all, timeout); } + /** + * @brief Creates a fence with initial value and flags. + * @param initial_value The initial value of the fence. + * @param flags The flags of the fence. + * @return wis::VKFence on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKFence CreateFence(wis::Result& result, uint64_t initial_value = 0, wis::FenceFlags flags = wis::FenceFlags::None) const noexcept + { + return wis::ImplVKDevice::CreateFence(result, initial_value, flags); + } /** * @brief Creates a fence with initial value and flags. * @param initial_value The initial value of the fence. @@ -298,7 +301,16 @@ class VKDevice : public wis::ImplVKDevice * */ [[nodiscard]] inline wis::ResultValue CreateFence(uint64_t initial_value = 0, wis::FenceFlags flags = wis::FenceFlags::None) const noexcept { - return wis::ImplVKDevice::CreateFence(initial_value, flags); + return wis::ResultValue{ &wis::ImplVKDevice::CreateFence, this, initial_value, flags }; + } + /** + * @brief Creates a command queue with specified type. + * @param type The type of the queue to create. + * @return wis::VKCommandQueue on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKCommandQueue CreateCommandQueue(wis::Result& result, wis::QueueType type) const noexcept + { + return wis::ImplVKDevice::CreateCommandQueue(result, type); } /** * @brief Creates a command queue with specified type. @@ -307,7 +319,16 @@ class VKDevice : public wis::ImplVKDevice * */ [[nodiscard]] inline wis::ResultValue CreateCommandQueue(wis::QueueType type) const noexcept { - return wis::ImplVKDevice::CreateCommandQueue(type); + return wis::ResultValue{ &wis::ImplVKDevice::CreateCommandQueue, this, type }; + } + /** + * @brief Creates a command list for specific queue type. + * @param type The type of the queue to create the command list for. + * @return wis::VKCommandList on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKCommandList CreateCommandList(wis::Result& result, wis::QueueType type) const noexcept + { + return wis::ImplVKDevice::CreateCommandList(result, type); } /** * @brief Creates a command list for specific queue type. @@ -316,16 +337,44 @@ class VKDevice : public wis::ImplVKDevice * */ [[nodiscard]] inline wis::ResultValue CreateCommandList(wis::QueueType type) const noexcept { - return wis::ImplVKDevice::CreateCommandList(type); + return wis::ResultValue{ &wis::ImplVKDevice::CreateCommandList, this, type }; } /** * @brief Creates a graphics pipeline state object. * @param desc The description of the graphics pipeline to create. * @return wis::VKPipelineState on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc* desc) const noexcept + [[nodiscard]] inline wis::VKPipelineState CreateGraphicsPipeline(wis::Result& result, const wis::VKGraphicsPipelineDesc& desc) const noexcept { - return wis::ImplVKDevice::CreateGraphicsPipeline(desc); + return wis::ImplVKDevice::CreateGraphicsPipeline(result, desc); + } + /** + * @brief Creates a graphics pipeline state object. + * @param desc The description of the graphics pipeline to create. + * @return wis::VKPipelineState on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateGraphicsPipeline(const wis::VKGraphicsPipelineDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplVKDevice::CreateGraphicsPipeline, this, desc }; + } + /** + * @brief Creates a root signature object for use with DescriptorStorage. + * @param push_constants The root constants to create the root signature with. + * @param constants_count The number of push constants. Max is 5. + * @param push_descriptors The root descriptors to create the root signature with. + * In shader will appear in order of submission. e.g. push_descriptors[5] is [[vk::binding(5,0)]] ... : register(b5/t5/u5) + * @param descriptors_count The number of push descriptors. Max is 8. + * @param space_overlap_count Count of descriptor spaces to overlap for each of the DescriptorStorage types. + * Default is 1. Max is 16. This is used primarily for descriptor type aliasing. + * Example: If wis::VKDevice is 2, that means that 2 descriptor spaces will be allocated for each descriptor type. + * [[vk::binding(0,0)]] SamplerState samplers: register(s0,space1); // space1 can be used for different type of samplers e.g. SamplerComparisonState + * [[vk::binding(0,0)]] SamplerComparisonState shadow_samplers: register(s0,space2); // they use the same binding (works like overloading) + * [[vk::binding(0,1)]] ConstantBuffer cbuffers: register(b0,space3); // this type also has 2 spaces, next will be on space 4 etc. + * @return wis::VKRootSignature on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKRootSignature CreateRootSignature(wis::Result& result, const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t descriptors_count = 0, uint32_t space_overlap_count = 1) const noexcept + { + return wis::ImplVKDevice::CreateRootSignature(result, push_constants, constants_count, push_descriptors, descriptors_count, space_overlap_count); } /** * @brief Creates a root signature object for use with DescriptorStorage. @@ -344,7 +393,23 @@ class VKDevice : public wis::ImplVKDevice * */ [[nodiscard]] inline wis::ResultValue CreateRootSignature(const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t descriptors_count = 0, uint32_t space_overlap_count = 1) const noexcept { - return wis::ImplVKDevice::CreateRootSignature(push_constants, constants_count, push_descriptors, descriptors_count, space_overlap_count); + return wis::ResultValue{ &wis::ImplVKDevice::CreateRootSignature, this, push_constants, constants_count, push_descriptors, descriptors_count, space_overlap_count }; + } + /** + * @brief Creates a root signature object for use with DescriptorStorage. + * Supplies number of types for each descriptor type separately. + * @param push_constants The root constants to create the root signature with. + * @param constants_count The number of push constants. Max is 5. + * @param push_descriptors The root descriptors to create the root signature with. + * In shader will appear in order of submission. e.g. root_descriptors[5] is [[vk::binding(5,0)]] ... : register(b5/t5/u5) + * @param push_descriptors_count The number of push descriptors. Max is 8. + * @param descriptor_spacing Descriptor spacing allocation. + * nullptr means allocate 1 space for each. + * @return wis::VKRootSignature on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKRootSignature CreateRootSignature2(wis::Result& result, const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_count = 0, const wis::DescriptorSpacing* descriptor_spacing = nullptr) const noexcept + { + return wis::ImplVKDevice::CreateRootSignature2(result, push_constants, constants_count, push_descriptors, push_descriptors_count, descriptor_spacing); } /** * @brief Creates a root signature object for use with DescriptorStorage. @@ -360,7 +425,17 @@ class VKDevice : public wis::ImplVKDevice * */ [[nodiscard]] inline wis::ResultValue CreateRootSignature2(const wis::PushConstant* push_constants = nullptr, uint32_t constants_count = 0, const wis::PushDescriptor* push_descriptors = nullptr, uint32_t push_descriptors_count = 0, const wis::DescriptorSpacing* descriptor_spacing = nullptr) const noexcept { - return wis::ImplVKDevice::CreateRootSignature2(push_constants, constants_count, push_descriptors, push_descriptors_count, descriptor_spacing); + return wis::ResultValue{ &wis::ImplVKDevice::CreateRootSignature2, this, push_constants, constants_count, push_descriptors, push_descriptors_count, descriptor_spacing }; + } + /** + * @brief Creates a shader object. + * @param data Shader bytecode. + * @param size The size of the shader data in bytes. For SPIR-V must be multiple of 4. + * @return wis::VKShader on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKShader CreateShader(wis::Result& result, void* data, uint32_t size) const noexcept + { + return wis::ImplVKDevice::CreateShader(result, data, size); } /** * @brief Creates a shader object. @@ -370,7 +445,15 @@ class VKDevice : public wis::ImplVKDevice * */ [[nodiscard]] inline wis::ResultValue CreateShader(void* data, uint32_t size) const noexcept { - return wis::ImplVKDevice::CreateShader(data, size); + return wis::ResultValue{ &wis::ImplVKDevice::CreateShader, this, data, size }; + } + /** + * @brief Creates a resource allocator object. + * @return wis::VKResourceAllocator on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKResourceAllocator CreateAllocator(wis::Result& result) const noexcept + { + return wis::ImplVKDevice::CreateAllocator(result); } /** * @brief Creates a resource allocator object. @@ -378,7 +461,10 @@ class VKDevice : public wis::ImplVKDevice * */ [[nodiscard]] inline wis::ResultValue CreateAllocator() const noexcept { - return wis::ImplVKDevice::CreateAllocator(); + return wis::ResultValue{ + &wis::ImplVKDevice::CreateAllocator, + this, + }; } /** * @brief Creates a render target object. @@ -386,9 +472,19 @@ class VKDevice : public wis::ImplVKDevice * @param desc The description of the render target to create. * @return wis::VKRenderTarget on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateRenderTarget(wis::VKTextureView texture, wis::RenderTargetDesc desc) const noexcept + [[nodiscard]] inline wis::VKRenderTarget CreateRenderTarget(wis::Result& result, wis::VKTextureView texture, const wis::RenderTargetDesc& desc) const noexcept { - return wis::ImplVKDevice::CreateRenderTarget(std::move(texture), desc); + return wis::ImplVKDevice::CreateRenderTarget(result, std::move(texture), desc); + } + /** + * @brief Creates a render target object. + * @param texture The texture view to create the render target with. + * @param desc The description of the render target to create. + * @return wis::VKRenderTarget on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateRenderTarget(wis::VKTextureView texture, const wis::RenderTargetDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplVKDevice::CreateRenderTarget, this, std::move(texture), desc }; } /** * @brief Creates a depth stencil target object. @@ -399,18 +495,50 @@ class VKDevice : public wis::ImplVKDevice * Does not work with 3D textures. * @return wis::VKRenderTarget on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateDepthStencilTarget(wis::VKTextureView texture, wis::RenderTargetDesc desc) const noexcept + [[nodiscard]] inline wis::VKRenderTarget CreateDepthStencilTarget(wis::Result& result, wis::VKTextureView texture, const wis::RenderTargetDesc& desc) const noexcept { - return wis::ImplVKDevice::CreateDepthStencilTarget(std::move(texture), desc); + return wis::ImplVKDevice::CreateDepthStencilTarget(result, std::move(texture), desc); + } + /** + * @brief Creates a depth stencil target object. + * Works only with depth formats. + * Used with render passes. + * @param texture The texture view to create the render target with. + * @param desc The description of the render target to create. + * Does not work with 3D textures. + * @return wis::VKRenderTarget on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateDepthStencilTarget(wis::VKTextureView texture, const wis::RenderTargetDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplVKDevice::CreateDepthStencilTarget, this, std::move(texture), desc }; } /** * @brief Creates a sampler object. * @param desc The description of the sampler to create. * @return wis::VKSampler on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateSampler(const wis::SamplerDesc* desc) const noexcept + [[nodiscard]] inline wis::VKSampler CreateSampler(wis::Result& result, const wis::SamplerDesc& desc) const noexcept + { + return wis::ImplVKDevice::CreateSampler(result, desc); + } + /** + * @brief Creates a sampler object. + * @param desc The description of the sampler to create. + * @return wis::VKSampler on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateSampler(const wis::SamplerDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplVKDevice::CreateSampler, this, desc }; + } + /** + * @brief Creates a shader resource object. + * @param texture The texture view to create the shader resource with. + * @param desc The description of the shader resource to create. + * @return wis::VKShaderResource on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKShaderResource CreateShaderResource(wis::Result& result, wis::VKTextureView texture, const wis::ShaderResourceDesc& desc) const noexcept { - return wis::ImplVKDevice::CreateSampler(desc); + return wis::ImplVKDevice::CreateShaderResource(result, std::move(texture), desc); } /** * @brief Creates a shader resource object. @@ -418,9 +546,29 @@ class VKDevice : public wis::ImplVKDevice * @param desc The description of the shader resource to create. * @return wis::VKShaderResource on success (wis::Status::Ok). * */ - [[nodiscard]] inline wis::ResultValue CreateShaderResource(wis::VKTextureView texture, wis::ShaderResourceDesc desc) const noexcept + [[nodiscard]] inline wis::ResultValue CreateShaderResource(wis::VKTextureView texture, const wis::ShaderResourceDesc& desc) const noexcept + { + return wis::ResultValue{ &wis::ImplVKDevice::CreateShaderResource, this, std::move(texture), desc }; + } + /** + * @brief Creates a descriptor storage object with specified number of bindings to allocate. + * Switching between several DescriptorStorage is slow, consider allocating one big set and copy descriptors to it. + * @param desc The description of the descriptor storage to create. + * @return wis::VKDescriptorStorage on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKDescriptorStorage CreateDescriptorStorage(wis::Result& result, const wis::DescriptorStorageDesc& desc) const noexcept + { + return wis::ImplVKDevice::CreateDescriptorStorage(result, desc); + } + /** + * @brief Creates a descriptor storage object with specified number of bindings to allocate. + * Switching between several DescriptorStorage is slow, consider allocating one big set and copy descriptors to it. + * @param desc The description of the descriptor storage to create. + * @return wis::VKDescriptorStorage on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::ResultValue CreateDescriptorStorage(const wis::DescriptorStorageDesc& desc) const noexcept { - return wis::ImplVKDevice::CreateShaderResource(std::move(texture), desc); + return wis::ResultValue{ &wis::ImplVKDevice::CreateDescriptorStorage, this, desc }; } /** * @brief Queries if the device supports the feature. @@ -434,8 +582,8 @@ class VKDevice : public wis::ImplVKDevice }; #pragma endregion VKDevice -[[nodiscard]] WIS_INLINE wis::ResultValue -ImplVKCreateDevice(wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts, uint32_t ext_size, bool force) noexcept; +[[nodiscard]] WIS_INLINE wis::VKDevice +ImplVKCreateDevice(wis::Result& result, wis::VKAdapter in_adapter, wis::VKDeviceExtension** exts, uint32_t ext_size, bool force) noexcept; } // namespace wis diff --git a/wisdom/include/wisdom/vulkan/vk_device_ext.h b/wisdom/include/wisdom/vulkan/vk_device_ext.h index a7ae4d2e..3d563fe9 100644 --- a/wisdom/include/wisdom/vulkan/vk_device_ext.h +++ b/wisdom/include/wisdom/vulkan/vk_device_ext.h @@ -1,6 +1,6 @@ #ifndef WIS_VK_DEVICE_EXT_H #define WIS_VK_DEVICE_EXT_H -#include +#include #include #include #include diff --git a/wisdom/include/wisdom/vulkan/vk_factory.h b/wisdom/include/wisdom/vulkan/vk_factory.h index 338cb593..be016a2d 100644 --- a/wisdom/include/wisdom/vulkan/vk_factory.h +++ b/wisdom/include/wisdom/vulkan/vk_factory.h @@ -86,12 +86,7 @@ class ImplVKFactory : public QueryInternal public: ImplVKFactory() noexcept = default; - WIS_INLINE explicit ImplVKFactory( - wis::SharedInstance instance, uint32_t api_ver, bool debug) noexcept; - - ImplVKFactory(const ImplVKFactory&) = delete; ImplVKFactory(ImplVKFactory&&) noexcept = default; - ImplVKFactory& operator=(const ImplVKFactory&) = delete; ImplVKFactory& operator=(ImplVKFactory&&) noexcept = default; operator bool() const noexcept @@ -104,17 +99,17 @@ class ImplVKFactory : public QueryInternal } public: - [[nodiscard]] WIS_INLINE wis::ResultValue - GetAdapter(uint32_t index, + [[nodiscard]] WIS_INLINE VKAdapter + GetAdapter(wis::Result& resutlt, uint32_t index, AdapterPreference preference = AdapterPreference::Performance) const noexcept; public: WIS_INLINE VkResult VKEnumeratePhysicalDevices() noexcept; - [[nodiscard]] static WIS_INLINE wis::ResultValue> - FoundExtensions(std::span in_extensions) noexcept; - [[nodiscard]] static WIS_INLINE wis::ResultValue> - FoundLayers(std::span in_layers) noexcept; + [[nodiscard]] static WIS_INLINE wis::detail::fixed_allocation + FoundExtensions(wis::Result& result, std::span in_extensions) noexcept; + [[nodiscard]] static WIS_INLINE wis::detail::fixed_allocation + FoundLayers(wis::Result& result, std::span in_layers) noexcept; private: mutable std::vector adapters{}; @@ -131,6 +126,17 @@ class VKFactory : public wis::ImplVKFactory using wis::ImplVKFactory::ImplVKFactory; public: + /** + * @brief Creates the wis::VKAdapter for the factory with provided index. + * @param index The index of the adapter to get. + * @param preference The preference of the adapter to get. + * Default is wis::AdapterPreference::Performance. + * @return wis::VKAdapter on success (wis::Status::Ok). + * */ + [[nodiscard]] inline wis::VKAdapter GetAdapter(wis::Result& result, uint32_t index, wis::AdapterPreference preference = wis::AdapterPreference::Performance) const noexcept + { + return wis::ImplVKFactory::GetAdapter(result, index, preference); + } /** * @brief Creates the wis::VKAdapter for the factory with provided index. * @param index The index of the adapter to get. @@ -140,21 +146,13 @@ class VKFactory : public wis::ImplVKFactory * */ [[nodiscard]] inline wis::ResultValue GetAdapter(uint32_t index, wis::AdapterPreference preference = wis::AdapterPreference::Performance) const noexcept { - return wis::ImplVKFactory::GetAdapter(index, preference); + return wis::ResultValue{ &wis::ImplVKFactory::GetAdapter, this, index, preference }; } }; #pragma endregion VKFactory -[[nodiscard]] WIS_INLINE wis::ResultValue -ImplVKCreateFactory(bool debug_layer, VKFactoryExtension** extensions, size_t extension_count) noexcept; - -namespace detail { -[[nodiscard]] WIS_INLINE wis::ResultValue -VKCreateFactoryEx(VkInstance instance, uint32_t version, bool debug_layer) noexcept; - -[[nodiscard]] WIS_INLINE wis::ResultValue -VKCreateFactoryWithExtensions(bool debug_layer, const char** exts, size_t extension_count, const char** layers, size_t layer_count) noexcept; -} // namespace detail +[[nodiscard]] WIS_INLINE wis::VKFactory +ImplVKCreateFactory(wis::Result& result, bool debug_layer, VKFactoryExtension** extensions, size_t extension_count) noexcept; } // namespace wis #ifndef WISDOM_BUILD_BINARIES diff --git a/wisdom/include/wisdom/vulkan/vk_factory_ext.h b/wisdom/include/wisdom/vulkan/vk_factory_ext.h index f991a593..268f0f86 100644 --- a/wisdom/include/wisdom/vulkan/vk_factory_ext.h +++ b/wisdom/include/wisdom/vulkan/vk_factory_ext.h @@ -1,6 +1,6 @@ #ifndef WIS_VK_FACTORY_EXT_H #define WIS_VK_FACTORY_EXT_H -#include +#include #include #include @@ -43,37 +43,41 @@ struct VKFactoryExtensionImpl : public VKFactoryExtension { virtual std::span GetRequiredExtensions() const noexcept override { - if constexpr (requires { T::required_extensions; }) + if constexpr (requires { T::required_extensions; }) { return T::required_extensions; - else + } else { return {}; + } } virtual size_t RequiredExtensionsSize() const noexcept override { - if constexpr (requires { T::required_extensions; }) + if constexpr (requires { T::required_extensions; }) { return T::required_extensions.size(); - else + } else { return 0; + } } virtual std::span GetRequiredLayers() const noexcept override { - if constexpr (requires { T::required_layers; }) + if constexpr (requires { T::required_layers; }) { return T::required_layers; - else + } else { return {}; + } } virtual size_t RequiredLayersSize() const noexcept { - if constexpr (requires { T::required_layers; }) + if constexpr (requires { T::required_layers; }) { return T::required_layers.size(); - else + } else { return 0; + } } }; } // namespace wis diff --git a/wisdom/include/wisdom/vulkan/vk_fence.h b/wisdom/include/wisdom/vulkan/vk_fence.h index 358ad3fd..c369e42e 100644 --- a/wisdom/include/wisdom/vulkan/vk_fence.h +++ b/wisdom/include/wisdom/vulkan/vk_fence.h @@ -18,10 +18,6 @@ class ImplVKFence : public QueryInternal { public: ImplVKFence() = default; - explicit ImplVKFence(wis::managed_handle_ex in_fence) noexcept - : QueryInternal(std::move(in_fence)) - { - } operator VKFenceView() const noexcept { return fence.get(); diff --git a/wisdom/include/wisdom/vulkan/vk_memory.h b/wisdom/include/wisdom/vulkan/vk_memory.h index f99e9d2f..e9765c0a 100644 --- a/wisdom/include/wisdom/vulkan/vk_memory.h +++ b/wisdom/include/wisdom/vulkan/vk_memory.h @@ -17,8 +17,6 @@ struct Internal { h::VmaAllocation allocation; Internal() noexcept = default; - Internal(wis::shared_handle allocator, ::VmaAllocation allocation) noexcept - : allocator(std::move(allocator)), allocation(allocation) { } Internal(Internal&&) noexcept = default; Internal& operator=(Internal&& o) noexcept { @@ -46,10 +44,6 @@ class ImplVKMemory : public QueryInternal { public: ImplVKMemory() noexcept = default; - explicit ImplVKMemory(wis::shared_handle allocator, VmaAllocation allocation) noexcept - : QueryInternal(std::move(allocator), allocation) - { - } operator bool() const noexcept { return bool(allocation); @@ -72,8 +66,9 @@ class ImplVKMemory : public QueryInternal public: [[nodiscard]] uint64_t GetBlockOffset() const noexcept { - if (!allocation) + if (!allocation) { return 0; + } VmaAllocationInfo2 info{}; vmaGetAllocationInfo2(allocator.get(), allocation, &info); diff --git a/wisdom/include/wisdom/vulkan/vk_pipeline_state.h b/wisdom/include/wisdom/vulkan/vk_pipeline_state.h index 0c4d7c30..34e6922b 100644 --- a/wisdom/include/wisdom/vulkan/vk_pipeline_state.h +++ b/wisdom/include/wisdom/vulkan/vk_pipeline_state.h @@ -16,10 +16,6 @@ class VKPipelineState : public QueryInternal { public: VKPipelineState() = default; - explicit VKPipelineState(wis::SharedPipeline pipeline) noexcept - : QueryInternal(std::move(pipeline)) - { - } operator VKPipelineView() const noexcept { return pipeline.get(); diff --git a/wisdom/include/wisdom/vulkan/vk_queue_residency.h b/wisdom/include/wisdom/vulkan/vk_queue_residency.h index 8f9e8527..13fdd031 100644 --- a/wisdom/include/wisdom/vulkan/vk_queue_residency.h +++ b/wisdom/include/wisdom/vulkan/vk_queue_residency.h @@ -2,7 +2,7 @@ #define WIS_VK_QUEUE_RESIDENCY_H #include #include -#include +#include #include #include @@ -97,8 +97,9 @@ struct QueueResidency { if (q->count == 0u) { idx = FindResembling(QueueTypes(idx)); - if (idx == -1) + if (idx == -1) { return nullptr; + } q = &available_queues[idx]; } return q; @@ -107,8 +108,9 @@ struct QueueResidency { { for (size_t i = 0; i < size_t(QueueTypes::Count); i++) { const auto& r = available_queues[i]; - if ((r.queue_flags & QueueFlag(type)) != 0u) + if ((r.queue_flags & QueueFlag(type)) != 0u) { return static_cast(i); + } } return -1; } diff --git a/wisdom/include/wisdom/vulkan/vk_resource.h b/wisdom/include/wisdom/vulkan/vk_resource.h index 9f3af141..62347c4e 100644 --- a/wisdom/include/wisdom/vulkan/vk_resource.h +++ b/wisdom/include/wisdom/vulkan/vk_resource.h @@ -2,7 +2,7 @@ #define WIS_VK_RESOURCE_H #include #include -#include +#include namespace wis { class VKBuffer; @@ -14,10 +14,6 @@ struct Internal { h::VkBuffer buffer; Internal() noexcept = default; - Internal(wis::shared_handle allocator, - VkBuffer buffer, - VmaAllocation allocation = nullptr) noexcept - : memory(std::move(allocator), allocation), buffer(buffer) { } Internal(Internal&&) noexcept = default; Internal& operator=(Internal&& o) noexcept { @@ -47,12 +43,6 @@ class ImplVKBuffer : public QueryInternal { public: ImplVKBuffer() noexcept = default; - explicit ImplVKBuffer(wis::shared_handle allocator, - VkBuffer buffer, - VmaAllocation allocation = nullptr) noexcept - : QueryInternal(std::move(allocator), buffer, allocation) - { - } operator VKBufferView() const noexcept { return { buffer }; @@ -88,10 +78,6 @@ class Internal wis::Size2D size{}; Internal() noexcept = default; - Internal(VkFormat format, VkImage buffer, wis::shared_handle allocator, VmaAllocation allocation, Size2D size) noexcept - : memory(std::move(allocator), allocation), buffer(buffer), format(format), size(size) - { - } Internal(Internal&& other) noexcept = default; Internal& operator=(Internal&& other) noexcept { @@ -123,10 +109,6 @@ class VKTexture : public QueryInternal { public: VKTexture() = default; - explicit VKTexture(VkFormat format, VkImage buffer, wis::Size2D size, wis::shared_handle allocator = {}, VmaAllocation allocation = nullptr) noexcept - : QueryInternal(format, std::move(buffer), std::move(allocator), allocation, size) - { - } operator VKTextureView() const noexcept { return { buffer, format, size }; @@ -150,10 +132,6 @@ class VKRenderTarget : public QueryInternal { public: VKRenderTarget() = default; - explicit VKRenderTarget(wis::managed_handle_ex view, wis::Size2D size) noexcept - : QueryInternal(std::move(view), size) - { - } operator bool() const noexcept { return bool(view); @@ -175,9 +153,6 @@ class VKSampler : public QueryInternal { public: VKSampler() noexcept = default; - explicit VKSampler(wis::managed_handle_ex sampler) noexcept - : QueryInternal(std::move(sampler)) { } - operator bool() const noexcept { return bool(sampler); @@ -201,9 +176,6 @@ class VKShaderResource : public QueryInternal { public: VKShaderResource() noexcept = default; - explicit VKShaderResource(wis::managed_handle_ex view) noexcept - : QueryInternal(std::move(view)) { } - operator bool() const noexcept { return bool(view); diff --git a/wisdom/include/wisdom/vulkan/vk_root_signature.h b/wisdom/include/wisdom/vulkan/vk_root_signature.h index 2ba6f71d..70ecb26d 100644 --- a/wisdom/include/wisdom/vulkan/vk_root_signature.h +++ b/wisdom/include/wisdom/vulkan/vk_root_signature.h @@ -14,11 +14,6 @@ struct Internal { uint32_t dsl_count = 0; Internal() noexcept = default; - Internal(wis::managed_handle_ex root, std::unique_ptr vk_dsls, uint32_t dsl_count) noexcept - : root(std::move(root)), vk_dsls(std::move(vk_dsls)), dsl_count(dsl_count) - { - } - Internal(Internal&&) noexcept = default; Internal& operator=(Internal&& o) noexcept { @@ -31,7 +26,6 @@ struct Internal { dsl_count = o.dsl_count; return *this; } - ~Internal() { Destroy(); @@ -53,10 +47,6 @@ class VKRootSignature : public QueryInternal { public: VKRootSignature() = default; - explicit VKRootSignature(wis::managed_handle_ex root, std::unique_ptr vk_dsls, uint32_t dsl_count) noexcept - : QueryInternal(std::move(root), std::move(vk_dsls), dsl_count) - { - } operator VKRootSignatureView() const noexcept { return root.get(); diff --git a/wisdom/include/wisdom/vulkan/vk_shader.h b/wisdom/include/wisdom/vulkan/vk_shader.h index 2a14f91f..d0ee738c 100644 --- a/wisdom/include/wisdom/vulkan/vk_shader.h +++ b/wisdom/include/wisdom/vulkan/vk_shader.h @@ -15,10 +15,6 @@ class VKShader : public QueryInternal { public: VKShader() = default; - explicit VKShader(wis::managed_handle_ex shader) noexcept - : QueryInternal(std::move(shader)) - { - } operator VKShaderView() const noexcept { return shader.get(); diff --git a/wisdom/include/wisdom/vulkan/vk_swapchain.h b/wisdom/include/wisdom/vulkan/vk_swapchain.h index 4f5c0b69..dc31df77 100644 --- a/wisdom/include/wisdom/vulkan/vk_swapchain.h +++ b/wisdom/include/wisdom/vulkan/vk_swapchain.h @@ -39,39 +39,8 @@ struct VKSwapChainCreateInfo { public: VKSwapChainCreateInfo() = default; - VKSwapChainCreateInfo(wis::SharedSurface surface, - wis::SharedDevice device, - VkPhysicalDevice adapter, - VkSwapchainKHR swapchain, - VkCommandBuffer initialization, - VkCommandPool command_pool, - VkQueue present_queue, - VkQueue graphics_queue, - VkSurfaceFormatKHR format, - VkPresentModeKHR present_mode, uint8_t supported_presentations, - bool tearing, - bool stereo, bool stereo_requested) noexcept - : surface(std::move(surface)) - , device(std::move(device)) - , adapter(adapter) - , swapchain(swapchain) - , initialization(initialization) - , command_pool(command_pool) - , present_queue(present_queue) - , graphics_queue(graphics_queue) - , format(format) - , present_mode(present_mode) - , supported_presentations(supported_presentations) - , tearing(tearing) - , stereo(stereo) - , stereo_requested(stereo_requested) - { - } - VKSwapChainCreateInfo(const VKSwapChainCreateInfo&) = delete; - VKSwapChainCreateInfo& operator=(const VKSwapChainCreateInfo&) = delete; VKSwapChainCreateInfo(VKSwapChainCreateInfo&&) noexcept = default; WIS_INLINE VKSwapChainCreateInfo& operator=(VKSwapChainCreateInfo&&) noexcept; - ~VKSwapChainCreateInfo() noexcept { Destroy(); @@ -80,7 +49,6 @@ struct VKSwapChainCreateInfo { WIS_INLINE void Destroy() noexcept; public: - [[nodiscard]] WIS_INLINE wis::Result InitSemaphores() noexcept; [[nodiscard]] WIS_INLINE wis::Result InitBackBuffers(VkExtent2D image_size) noexcept; [[nodiscard]] WIS_INLINE wis::Result AcquireNextIndex() const noexcept; [[nodiscard]] WIS_INLINE wis::Result AcquireNextIndexAndWait() const noexcept; @@ -96,10 +64,6 @@ class ImplVKSwapChain : public QueryInternal { public: ImplVKSwapChain() = default; - explicit ImplVKSwapChain(detail::VKSwapChainCreateInfo internals) noexcept - : QueryInternal(std::move(internals)) - { - } operator bool() const noexcept { return bool(swapchain); diff --git a/wisdom/include/wisdom/vulkan/vk_views.h b/wisdom/include/wisdom/vulkan/vk_views.h index 53cdb7dd..2223021e 100644 --- a/wisdom/include/wisdom/vulkan/vk_views.h +++ b/wisdom/include/wisdom/vulkan/vk_views.h @@ -5,7 +5,7 @@ #include #include #include -#include +#include namespace wis { using VKFactoryHandle = std::tuple; diff --git a/wisdom/include/wisdom/wisdom.hpp b/wisdom/include/wisdom/wisdom.hpp index 1f996c5d..1bd4f2ec 100644 --- a/wisdom/include/wisdom/wisdom.hpp +++ b/wisdom/include/wisdom/wisdom.hpp @@ -52,6 +52,18 @@ using ShaderResource = DX12ShaderResource; //------------------------------------------------------------------------- +/** + * @brief Creates the wis::Factory with extensions, specified in extension array. + * @param debug_layer Enable the debug layer for underlying API. + * @param extensions The extensions to enable. + * The extensions are initialized through this array. + * @param extension_count The number of extensions to enable. + * @return wis::Factory on success (wis::Status::Ok). + * */ +inline wis::Factory CreateFactory(wis::Result& result, bool debug_layer = false, wis::FactoryExtension** extensions = nullptr, uint32_t extension_count = 0) +{ + return DX12CreateFactory(result, debug_layer, extensions, extension_count); +} /** * @brief Creates the wis::Factory with extensions, specified in extension array. * @param debug_layer Enable the debug layer for underlying API. @@ -64,6 +76,20 @@ inline wis::ResultValue CreateFactory(bool debug_layer = false, wi { return DX12CreateFactory(debug_layer, extensions, extension_count); } +/** + * @brief Creates the wis::Device with extensions, specified in extension array. + * @param adapter The adapter to create the logical device on. Must not be NULL. + * @param extensions The extensions to enable. + * The extensions are initialized through this array. + * @param extension_count The number of extensions to enable. + * @param force Create logical device even if some core functionality is absent. + * The presence of core functionality is checked by the query function. + * @return wis::Device on success (wis::Status::Ok). + * */ +inline wis::Device CreateDevice(wis::Result& result, wis::Adapter adapter, wis::DeviceExtension** extensions = nullptr, uint32_t extension_count = 0, bool force = false) +{ + return DX12CreateDevice(result, std::move(adapter), extensions, extension_count, force); +} /** * @brief Creates the wis::Device with extensions, specified in extension array. * @param adapter The adapter to create the logical device on. Must not be NULL. @@ -134,6 +160,18 @@ using ShaderResource = VKShaderResource; //------------------------------------------------------------------------- +/** + * @brief Creates the wis::Factory with extensions, specified in extension array. + * @param debug_layer Enable the debug layer for underlying API. + * @param extensions The extensions to enable. + * The extensions are initialized through this array. + * @param extension_count The number of extensions to enable. + * @return wis::Factory on success (wis::Status::Ok). + * */ +inline wis::Factory CreateFactory(wis::Result& result, bool debug_layer = false, wis::FactoryExtension** extensions = nullptr, uint32_t extension_count = 0) +{ + return VKCreateFactory(result, debug_layer, extensions, extension_count); +} /** * @brief Creates the wis::Factory with extensions, specified in extension array. * @param debug_layer Enable the debug layer for underlying API. @@ -146,6 +184,20 @@ inline wis::ResultValue CreateFactory(bool debug_layer = false, wi { return VKCreateFactory(debug_layer, extensions, extension_count); } +/** + * @brief Creates the wis::Device with extensions, specified in extension array. + * @param adapter The adapter to create the logical device on. Must not be NULL. + * @param extensions The extensions to enable. + * The extensions are initialized through this array. + * @param extension_count The number of extensions to enable. + * @param force Create logical device even if some core functionality is absent. + * The presence of core functionality is checked by the query function. + * @return wis::Device on success (wis::Status::Ok). + * */ +inline wis::Device CreateDevice(wis::Result& result, wis::Adapter adapter, wis::DeviceExtension** extensions = nullptr, uint32_t extension_count = 0, bool force = false) +{ + return VKCreateDevice(result, std::move(adapter), extensions, extension_count, force); +} /** * @brief Creates the wis::Device with extensions, specified in extension array. * @param adapter The adapter to create the logical device on. Must not be NULL. diff --git a/wisdom/include/wisdom/wisdom_dx12.hpp b/wisdom/include/wisdom/wisdom_dx12.hpp index f1eb5aaf..8b8097ae 100644 --- a/wisdom/include/wisdom/wisdom_dx12.hpp +++ b/wisdom/include/wisdom/wisdom_dx12.hpp @@ -14,9 +14,35 @@ namespace wis { * @param extension_count The number of extensions to enable. * @return wis::DX12Factory on success (wis::Status::Ok). * */ -inline wis::ResultValue DX12CreateFactory(bool debug_layer = false, wis::DX12FactoryExtension** extensions = nullptr, uint32_t extension_count = 0) +[[nodiscard]] inline wis::DX12Factory DX12CreateFactory(wis::Result& result, bool debug_layer = false, wis::DX12FactoryExtension** extensions = nullptr, uint32_t extension_count = 0) { - return wis::ImplDX12CreateFactory(debug_layer, extensions, extension_count); + return wis::ImplDX12CreateFactory(result, debug_layer, extensions, extension_count); +} +/** + * @brief Creates the wis::DX12Factory with extensions, specified in extension array. + * @param debug_layer Enable the debug layer for underlying API. + * @param extensions The extensions to enable. + * The extensions are initialized through this array. + * @param extension_count The number of extensions to enable. + * @return wis::DX12Factory on success (wis::Status::Ok). + * */ +[[nodiscard]] inline wis::ResultValue DX12CreateFactory(bool debug_layer = false, wis::DX12FactoryExtension** extensions = nullptr, uint32_t extension_count = 0) noexcept +{ + return wis::ResultValue{ &wis::ImplDX12CreateFactory, debug_layer, extensions, extension_count }; +} +/** + * @brief Creates the wis::DX12Device with extensions, specified in extension array. + * @param adapter The adapter to create the logical device on. Must not be NULL. + * @param extensions The extensions to enable. + * The extensions are initialized through this array. + * @param extension_count The number of extensions to enable. + * @param force Create logical device even if some core functionality is absent. + * The presence of core functionality is checked by the query function. + * @return wis::DX12Device on success (wis::Status::Ok). + * */ +[[nodiscard]] inline wis::DX12Device DX12CreateDevice(wis::Result& result, wis::DX12Adapter adapter, wis::DX12DeviceExtension** extensions = nullptr, uint32_t extension_count = 0, bool force = false) +{ + return wis::ImplDX12CreateDevice(result, std::move(adapter), extensions, extension_count, force); } /** * @brief Creates the wis::DX12Device with extensions, specified in extension array. @@ -28,9 +54,9 @@ inline wis::ResultValue DX12CreateFactory(bool debug_layer = f * The presence of core functionality is checked by the query function. * @return wis::DX12Device on success (wis::Status::Ok). * */ -inline wis::ResultValue DX12CreateDevice(wis::DX12Adapter adapter, wis::DX12DeviceExtension** extensions = nullptr, uint32_t extension_count = 0, bool force = false) +[[nodiscard]] inline wis::ResultValue DX12CreateDevice(wis::DX12Adapter adapter, wis::DX12DeviceExtension** extensions = nullptr, uint32_t extension_count = 0, bool force = false) noexcept { - return wis::ImplDX12CreateDevice(std::move(adapter), extensions, extension_count, force); + return wis::ResultValue{ &wis::ImplDX12CreateDevice, std::move(adapter), extensions, extension_count, force }; } //------------------------------------------------------------------------- diff --git a/wisdom/include/wisdom/wisdom_vk.hpp b/wisdom/include/wisdom/wisdom_vk.hpp index 8bdb9238..e79bb41f 100644 --- a/wisdom/include/wisdom/wisdom_vk.hpp +++ b/wisdom/include/wisdom/wisdom_vk.hpp @@ -14,9 +14,35 @@ namespace wis { * @param extension_count The number of extensions to enable. * @return wis::VKFactory on success (wis::Status::Ok). * */ -inline wis::ResultValue VKCreateFactory(bool debug_layer = false, wis::VKFactoryExtension** extensions = nullptr, uint32_t extension_count = 0) +[[nodiscard]] inline wis::VKFactory VKCreateFactory(wis::Result& result, bool debug_layer = false, wis::VKFactoryExtension** extensions = nullptr, uint32_t extension_count = 0) { - return wis::ImplVKCreateFactory(debug_layer, extensions, extension_count); + return wis::ImplVKCreateFactory(result, debug_layer, extensions, extension_count); +} +/** + * @brief Creates the wis::VKFactory with extensions, specified in extension array. + * @param debug_layer Enable the debug layer for underlying API. + * @param extensions The extensions to enable. + * The extensions are initialized through this array. + * @param extension_count The number of extensions to enable. + * @return wis::VKFactory on success (wis::Status::Ok). + * */ +[[nodiscard]] inline wis::ResultValue VKCreateFactory(bool debug_layer = false, wis::VKFactoryExtension** extensions = nullptr, uint32_t extension_count = 0) noexcept +{ + return wis::ResultValue{ &wis::ImplVKCreateFactory, debug_layer, extensions, extension_count }; +} +/** + * @brief Creates the wis::VKDevice with extensions, specified in extension array. + * @param adapter The adapter to create the logical device on. Must not be NULL. + * @param extensions The extensions to enable. + * The extensions are initialized through this array. + * @param extension_count The number of extensions to enable. + * @param force Create logical device even if some core functionality is absent. + * The presence of core functionality is checked by the query function. + * @return wis::VKDevice on success (wis::Status::Ok). + * */ +[[nodiscard]] inline wis::VKDevice VKCreateDevice(wis::Result& result, wis::VKAdapter adapter, wis::VKDeviceExtension** extensions = nullptr, uint32_t extension_count = 0, bool force = false) +{ + return wis::ImplVKCreateDevice(result, std::move(adapter), extensions, extension_count, force); } /** * @brief Creates the wis::VKDevice with extensions, specified in extension array. @@ -28,9 +54,9 @@ inline wis::ResultValue VKCreateFactory(bool debug_layer = false * The presence of core functionality is checked by the query function. * @return wis::VKDevice on success (wis::Status::Ok). * */ -inline wis::ResultValue VKCreateDevice(wis::VKAdapter adapter, wis::VKDeviceExtension** extensions = nullptr, uint32_t extension_count = 0, bool force = false) +[[nodiscard]] inline wis::ResultValue VKCreateDevice(wis::VKAdapter adapter, wis::VKDeviceExtension** extensions = nullptr, uint32_t extension_count = 0, bool force = false) noexcept { - return wis::ImplVKCreateDevice(std::move(adapter), extensions, extension_count, force); + return wis::ResultValue{ &wis::ImplVKCreateDevice, std::move(adapter), extensions, extension_count, force }; } //------------------------------------------------------------------------- diff --git a/wisdom/platform/CMakeLists.txt b/wisdom/platform/CMakeLists.txt index 933a1299..fd0edabc 100644 --- a/wisdom/platform/CMakeLists.txt +++ b/wisdom/platform/CMakeLists.txt @@ -1,14 +1,14 @@ set(AUX_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../cmake) set(PLATFORM_CONFIG_DIR "${AUX_CMAKE_DIR}/platform") -add_library(wisdom-platform-headers INTERFACE "wisdom/wisdom_platform.h") +add_library(wisdom-platform-headers INTERFACE "wisdom/wisdom_platform.hpp") add_library(wis::platform-headers ALIAS wisdom-platform-headers) target_include_directories( wisdom-platform-headers INTERFACE $ $) -add_library(wisdom-platform INTERFACE "wisdom/wisdom_platform.h" - "wisdom/linux/interop_device.h") +add_library(wisdom-platform INTERFACE "wisdom/wisdom_platform.hpp" + "wisdom/linux/interop_device.hpp") add_library(wis::platform ALIAS wisdom-platform) target_include_directories( wisdom-platform INTERFACE $ diff --git a/wisdom/platform/wayland/CMakeLists.txt b/wisdom/platform/wayland/CMakeLists.txt index 4d16a614..4b1ace4f 100644 --- a/wisdom/platform/wayland/CMakeLists.txt +++ b/wisdom/platform/wayland/CMakeLists.txt @@ -16,7 +16,7 @@ target_include_directories( $) if(WISDOM_BUILD_BINARIES) - add_library(wisdom-wayland STATIC "wisdom/wisdom_wayland.h" + add_library(wisdom-wayland STATIC "wisdom/wisdom_wayland.hpp" "wisdom/wisdom_wayland.cpp") add_library(wis::wayland ALIAS wisdom-wayland) target_link_libraries(wisdom-wayland PUBLIC wis::wisdom) @@ -39,15 +39,13 @@ install( LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} INCLUDES - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install( EXPORT wisdom-wayland-targets FILE wisdom-wayland-targets.cmake NAMESPACE wis:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wisdom - ) + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wisdom) include(CMakePackageConfigHelpers) configure_package_config_file( @@ -55,12 +53,8 @@ configure_package_config_file( "${CMAKE_CURRENT_BINARY_DIR}/wisdom-wayland-config.cmake" INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wisdom) -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/wisdom-wayland-config.cmake" - - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/wisdom") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/wisdom-wayland-config.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/wisdom") -install( - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wisdom/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wisdom - ) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wisdom/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wisdom) diff --git a/wisdom/platform/wayland/wisdom/wisdom_wayland.cpp b/wisdom/platform/wayland/wisdom/wisdom_wayland.cpp index 8bb667df..d44257d5 100644 --- a/wisdom/platform/wayland/wisdom/wisdom_wayland.cpp +++ b/wisdom/platform/wayland/wisdom/wisdom_wayland.cpp @@ -1,12 +1,12 @@ #ifndef WISDOM_WAYLAND_CPP #define WISDOM_WAYLAND_CPP -#include +#include #include #include -wis::ResultValue -wis::platform::WaylandExtension::CreateSwapchain(const wis::VKDevice& device, wis::VKQueueView main_queue, const wis::SwapchainDesc* desc, wl_display* display, wl_surface* surface) const noexcept +wis::VKSwapChain +wis::platform::WaylandExtension::CreateSwapchain(wis::Result& result, const wis::VKDevice& device, wis::VKQueueView main_queue, const wis::SwapchainDesc* desc, wl_display* display, wl_surface* surface) const noexcept { VkWaylandSurfaceCreateInfoKHR surface_desc{ .sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, @@ -20,12 +20,12 @@ wis::platform::WaylandExtension::CreateSwapchain(const wis::VKDevice& device, wi auto& devicei = device.GetInternal(); const auto& instance_table = instance.table(); VkSurfaceKHR out_surface; - auto result = vkCreateWaylandSurfaceKHR(instance.get(), &surface_desc, nullptr, &out_surface); - if (!wis::succeeded(result)) { - return wis::make_result(result); + auto vr = vkCreateWaylandSurfaceKHR(instance.get(), &surface_desc, nullptr, &out_surface); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return {}; } - wis::SharedSurface surface_handle{ out_surface, instance, instance_table.vkDestroySurfaceKHR }; - return device.VKCreateSwapChain(surface_handle, desc, std::get<0>(main_queue)); + return device.VKCreateSwapChain(result, wis::SharedSurface{ out_surface, instance, instance_table.vkDestroySurfaceKHR }, desc, std::get<0>(main_queue)); } #endif // WISDOM_WAYLAND_CPP diff --git a/wisdom/platform/wayland/wisdom/wisdom_wayland.h b/wisdom/platform/wayland/wisdom/wisdom_wayland.hpp similarity index 74% rename from wisdom/platform/wayland/wisdom/wisdom_wayland.h rename to wisdom/platform/wayland/wisdom/wisdom_wayland.hpp index 796fae4d..d126d48d 100644 --- a/wisdom/platform/wayland/wisdom/wisdom_wayland.h +++ b/wisdom/platform/wayland/wisdom/wisdom_wayland.hpp @@ -47,8 +47,15 @@ class WaylandExtension : public QueryInternalExtension - CreateSwapchain(const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, wl_display* display, wl_surface* surface) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKSwapChain + CreateSwapchain(wis::Result& result, const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, wl_display* display, wl_surface* surface) const noexcept; + + [[nodiscard]] inline wis::ResultValue + CreateSwapchain(const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, wl_display* display, wl_surface* surface) const noexcept + { + auto fptr = static_cast(&platform::WaylandExtension::CreateSwapchain); + return wis::ResultValue::from_member_func(fptr, this, device, main_queue, desc, display, surface); + } }; } // namespace platform } // namespace wis diff --git a/wisdom/platform/windows/CMakeLists.txt b/wisdom/platform/windows/CMakeLists.txt index 13bbc8ac..f4245cd6 100644 --- a/wisdom/platform/windows/CMakeLists.txt +++ b/wisdom/platform/windows/CMakeLists.txt @@ -9,7 +9,7 @@ target_include_directories( $) if(WISDOM_BUILD_BINARIES) - add_library(wisdom-windows STATIC "wisdom/wisdom_windows.h" + add_library(wisdom-windows STATIC "wisdom/wisdom_windows.hpp" "wisdom/wisdom_windows.cpp") add_library(wis::windows ALIAS wisdom-windows) target_link_libraries(wisdom-windows PUBLIC wis::wisdom d3d11) @@ -32,15 +32,13 @@ install( LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} INCLUDES - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install( EXPORT wisdom-windows-targets FILE wisdom-windows-targets.cmake NAMESPACE wis:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wisdom - ) + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wisdom) include(CMakePackageConfigHelpers) configure_package_config_file( @@ -48,12 +46,8 @@ configure_package_config_file( "${CMAKE_CURRENT_BINARY_DIR}/wisdom-windows-config.cmake" INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wisdom) -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/wisdom-windows-config.cmake" - - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/wisdom") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/wisdom-windows-config.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/wisdom") -install( - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wisdom/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wisdom - ) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wisdom/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wisdom) diff --git a/wisdom/platform/windows/wisdom/wisdom_windows.cpp b/wisdom/platform/windows/wisdom/wisdom_windows.cpp index 52e0d868..f78f980d 100644 --- a/wisdom/platform/windows/wisdom/wisdom_windows.cpp +++ b/wisdom/platform/windows/wisdom/wisdom_windows.cpp @@ -1,6 +1,6 @@ #ifndef WISDOM_WINDOWS_CPP #define WISDOM_WINDOWS_CPP -#include +#include #include #include #include @@ -38,9 +38,12 @@ inline wis::com_ptr CreateD3D11Device() noexcept } // namespace wis::detail -wis::ResultValue -wis::platform::DX12WindowsExtension::CreateSwapchain(const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept +wis::DX12SwapChain +wis::platform::DX12WindowsExtension::CreateSwapchain(wis::Result& result, const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept { + DX12SwapChain out_swapchain; + auto& internal = out_swapchain.GetMutableInternal(); + DXGI_SWAP_CHAIN_DESC1 swap_desc; detail::ToSwapchainDesc(swap_desc, desc); auto& devicei = device.GetInternal(); @@ -56,15 +59,16 @@ wis::platform::DX12WindowsExtension::CreateSwapchain(const DX12Device& device, D factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &xtearing, sizeof(xtearing)); return bool(xtearing); }(); - if (tearing && desc->tearing) + if (tearing && desc->tearing) { swap_desc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + } HRESULT hr; wis::com_ptr swap; // until microsoft fixes this if (desc->stereo && !wis::succeeded(hr = devicei.factory->CreateSwapChainForHwnd(detail::CreateD3D11Device().get(), hwnd, &swap_desc, nullptr, nullptr, swap.put()))) { - return wis::make_result(hr); + result = wis::make_result(hr); } hr = devicei.factory->CreateSwapChainForHwnd( @@ -76,36 +80,39 @@ wis::platform::DX12WindowsExtension::CreateSwapchain(const DX12Device& device, D swap.put()); if (!wis::succeeded(hr)) { - return wis::make_result(hr); + result = wis::make_result(hr); + return out_swapchain; } - auto [hrx, swap4] = swap.as(); - if (!wis::succeeded(hrx)) { - return wis::make_result(hr); + hr = swap.as(&internal.chain); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_swapchain; } - auto hnd = swap4->GetFrameLatencyWaitableObject(); + internal.present_event = internal.chain->GetFrameLatencyWaitableObject(); + internal.stereo = swap_desc.Stereo; + internal.vsync = desc->vsync; + internal.tearing = tearing && desc->tearing; - wis::detail::DX12SwapChainCreateInfo create_info{ - .chain = std::move(swap4), - .present_event{ hnd }, - .stereo = desc->stereo, - .vsync = desc->vsync, - .tearing = tearing && desc->tearing, - }; - if (auto resw = create_info.InitBackBuffers(); resw.status != wis::Status::Ok) - return resw; + if (auto resw = internal.InitBackBuffers(); resw.status != wis::Status::Ok) { + result = resw; + } - return DX12SwapChain{ std::move(create_info) }; + return out_swapchain; } -wis::ResultValue -wis::platform::DX12WindowsExtension::CreateSwapchainUWP(const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, IUnknown* window) const noexcept +wis::DX12SwapChain +wis::platform::DX12WindowsExtension::CreateSwapchainUWP(wis::Result& result, const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, IUnknown* window) const noexcept { + DX12SwapChain out_swapchain; + auto& internal = out_swapchain.GetMutableInternal(); + DXGI_SWAP_CHAIN_DESC1 swap_desc; detail::ToSwapchainDesc(swap_desc, desc); auto& devicei = device.GetInternal(); swap_desc.Stereo &= devicei.factory->IsWindowedStereoEnabled(); + bool tearing = [&]() { auto [hr, factory5] = devicei.factory.as(); if (!wis::succeeded(hr)) { @@ -115,15 +122,16 @@ wis::platform::DX12WindowsExtension::CreateSwapchainUWP(const DX12Device& device factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &xtearing, sizeof(xtearing)); return bool(xtearing); }(); - if (tearing) + if (tearing && desc->tearing) { swap_desc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + } HRESULT hr; wis::com_ptr swap; // until microsoft fixes this if (desc->stereo && !wis::succeeded(hr = devicei.factory->CreateSwapChainForCoreWindow(detail::CreateD3D11Device().get(), window, &swap_desc, nullptr, swap.put()))) { - return wis::make_result(hr); + result = wis::make_result(hr); } hr = devicei.factory->CreateSwapChainForCoreWindow( @@ -134,25 +142,25 @@ wis::platform::DX12WindowsExtension::CreateSwapchainUWP(const DX12Device& device swap.put()); if (!wis::succeeded(hr)) { - return wis::make_result(hr); + result = wis::make_result(hr); + return out_swapchain; } - auto [hrx, swap4] = swap.as(); - if (!wis::succeeded(hrx)) { - return wis::make_result(hr); + hr = swap.as(&internal.chain); + if (!wis::succeeded(hr)) { + result = wis::make_result(hr); + return out_swapchain; + } + + internal.present_event = internal.chain->GetFrameLatencyWaitableObject(); + internal.stereo = swap_desc.Stereo; + internal.vsync = desc->vsync; + internal.tearing = tearing && desc->tearing; + + if (auto resw = internal.InitBackBuffers(); resw.status != wis::Status::Ok) { + result = resw; } - auto hnd = swap4->GetFrameLatencyWaitableObject(); - - wis::detail::DX12SwapChainCreateInfo create_info{ - .chain = std::move(swap4), - .present_event{ hnd }, - .stereo = desc->stereo, - .vsync = desc->vsync, - .tearing = tearing, - }; - if (auto resw = create_info.InitBackBuffers(); resw.status != wis::Status::Ok) - return resw; - return DX12SwapChain{ std::move(create_info) }; + return out_swapchain; } #ifdef WISDOM_VULKAN @@ -160,8 +168,8 @@ wis::platform::DX12WindowsExtension::CreateSwapchainUWP(const DX12Device& device // #error error -wis::ResultValue -wis::platform::VKWindowsExtension::CreateSwapchain(const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept +wis::VKSwapChain +wis::platform::VKWindowsExtension::CreateSwapchain(wis::Result& result, const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept { VkWin32SurfaceCreateInfoKHR surface_desc{ .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, @@ -175,12 +183,13 @@ wis::platform::VKWindowsExtension::CreateSwapchain(const VKDevice& device, VKQue auto& devicei = device.GetInternal(); const auto& instance_table = instance.table(); VkSurfaceKHR surface; - auto result = vkCreateWin32SurfaceKHR(instance.get(), &surface_desc, nullptr, &surface); - if (!wis::succeeded(result)) { - return wis::make_result(result); + auto vr = vkCreateWin32SurfaceKHR(instance.get(), &surface_desc, nullptr, &surface); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return {}; } wis::SharedSurface surface_handle{ surface, instance, instance_table.vkDestroySurfaceKHR }; - return device.VKCreateSwapChain(surface_handle, desc, std::get<0>(main_queue)); + return device.VKCreateSwapChain(result, surface_handle, desc, std::get<0>(main_queue)); } bool wis::platform::VKInteropDeviceExtension::GetExtensionInfo(const std::unordered_map>& available_extensions, diff --git a/wisdom/platform/windows/wisdom/wisdom_windows.h b/wisdom/platform/windows/wisdom/wisdom_windows.hpp similarity index 68% rename from wisdom/platform/windows/wisdom/wisdom_windows.h rename to wisdom/platform/windows/wisdom/wisdom_windows.hpp index 0bce515f..6a157f07 100644 --- a/wisdom/platform/windows/wisdom/wisdom_windows.h +++ b/wisdom/platform/windows/wisdom/wisdom_windows.hpp @@ -25,11 +25,24 @@ namespace platform { class DX12WindowsExtension : public QueryInternalExtension { public: - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateSwapchain(const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept; + [[nodiscard]] WIS_INLINE wis::DX12SwapChain + CreateSwapchain(wis::Result& result, const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept; - [[nodiscard]] WIS_INLINE wis::ResultValue - CreateSwapchainUWP(const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, IUnknown* window) const noexcept; + [[nodiscard]] inline wis::ResultValue + CreateSwapchain(const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept + { + auto fptr = static_cast(&DX12WindowsExtension::CreateSwapchain); + return wis::ResultValue::from_member_func(fptr, this, device, main_queue, desc, hwnd); + } + + [[nodiscard]] WIS_INLINE wis::DX12SwapChain + CreateSwapchainUWP(wis::Result& result, const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, IUnknown* window) const noexcept; + [[nodiscard]] inline wis::ResultValue + CreateSwapchainUWP(const DX12Device& device, DX12QueueView main_queue, const wis::SwapchainDesc* desc, IUnknown* window) const noexcept + { + auto fptr = static_cast(&DX12WindowsExtension::CreateSwapchainUWP); + return wis::ResultValue::from_member_func(fptr, this, device, main_queue, desc, window); + } }; class DX12InteropDeviceExtension : public QueryInternalExtension @@ -42,19 +55,20 @@ class DX12InteropDeviceExtension : public QueryInternalExtension - GetSemaphoreHandle(const wis::DX12Fence& fence) const noexcept + [[nodiscard]] WIS_INLINE HANDLE + GetSemaphoreHandle(wis::Result& result, const wis::DX12Fence& fence) const noexcept { HANDLE handle; auto hr = device->CreateSharedHandle(fence.GetInternal().fence.get(), nullptr, GENERIC_ALL, nullptr, &handle); if (!wis::succeeded(hr)) { - return wis::make_result(hr); + result = wis::make_result(hr); } return handle; } - [[nodiscard]] WIS_INLINE wis::ResultValue - GetMemoryHandle(wis::DX12MemoryView memory) const noexcept + + [[nodiscard]] WIS_INLINE HANDLE + GetMemoryHandle(wis::Result& result, wis::DX12MemoryView memory) const noexcept { auto allocation = std::get<1>(memory); @@ -62,7 +76,7 @@ class DX12InteropDeviceExtension : public QueryInternalExtensionCreateSharedHandle(allocation->GetHeap(), nullptr, GENERIC_ALL, nullptr, &handle); if (!wis::succeeded(hr)) { - return wis::make_result(hr); + result = wis::make_result(hr); } return handle; } @@ -124,8 +138,14 @@ class VKWindowsExtension : public QueryInternalExtension - CreateSwapchain(const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKSwapChain + CreateSwapchain(wis::Result& result, const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept; + [[nodiscard]] inline wis::ResultValue + CreateSwapchain(const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, HWND hwnd) const noexcept + { + auto fptr = static_cast(&VKWindowsExtension::CreateSwapchain); + return wis::ResultValue::from_member_func(fptr, this, device, main_queue, desc, hwnd); + } }; // Device Extension for memory and semaphore interop @@ -150,8 +170,8 @@ class VKInteropDeviceExtension : public QueryInternalExtension - GetSemaphoreHandle(const wis::VKFence& fence) const noexcept + [[nodiscard]] WIS_INLINE HANDLE + GetSemaphoreHandle(wis::Result& result, const wis::VKFence& fence) const noexcept { HANDLE handle; VkSemaphoreGetWin32HandleInfoKHR handle_info{ @@ -160,14 +180,14 @@ class VKInteropDeviceExtension : public QueryInternalExtension(result); + auto vr = vkGetSemaphoreWin32HandleKHR(device.get(), &handle_info, &handle); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); } return handle; } - [[nodiscard]] WIS_INLINE wis::ResultValue - GetMemoryHandle(wis::VKMemoryView memory) const noexcept + [[nodiscard]] WIS_INLINE HANDLE + GetMemoryHandle(wis::Result& result, wis::VKMemoryView memory) const noexcept { // I know it exists, but platform code is the pain in the ass :( extern VMA_CALL_PRE VkResult VMA_CALL_POST vmaGetMemoryWin32Handle(VmaAllocator VMA_NOT_NULL allocator, @@ -178,9 +198,9 @@ class VKInteropDeviceExtension : public QueryInternalExtension(memory); auto allocation = std::get<1>(memory); HANDLE handle; - auto result = vmaGetMemoryWin32Handle(allocator, allocation, nullptr, &handle); - if (!wis::succeeded(result)) { - return wis::make_result(result); + auto vr = vmaGetMemoryWin32Handle(allocator, allocation, nullptr, &handle); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); } return handle; } diff --git a/wisdom/platform/wisdom/linux/interop_device.h b/wisdom/platform/wisdom/linux/interop_device.hpp similarity index 85% rename from wisdom/platform/wisdom/linux/interop_device.h rename to wisdom/platform/wisdom/linux/interop_device.hpp index 67f3782c..39fe6446 100644 --- a/wisdom/platform/wisdom/linux/interop_device.h +++ b/wisdom/platform/wisdom/linux/interop_device.hpp @@ -57,8 +57,8 @@ class VKInteropDeviceExtensionLinux : public QueryInternalExtension - GetSemaphoreHandle(const wis::VKFence& fence) const noexcept + [[nodiscard]] WIS_INLINE int + GetSemaphoreHandle(wis::Result& result, const wis::VKFence& fence) const noexcept { int handle; VkSemaphoreGetFdInfoKHR handle_info{ @@ -67,14 +67,14 @@ class VKInteropDeviceExtensionLinux : public QueryInternalExtension(result); + auto vr = vkGetSemaphoreFdKHR(device.get(), &handle_info, &handle); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); } return handle; } - [[nodiscard]] WIS_INLINE wis::ResultValue - GetMemoryHandle(wis::VKMemoryView memory) const noexcept + [[nodiscard]] WIS_INLINE int + GetMemoryHandle(wis::Result& result, wis::VKMemoryView memory) const noexcept { int handle; auto allocator = std::get<0>(memory); @@ -93,9 +93,9 @@ class VKInteropDeviceExtensionLinux : public QueryInternalExtension(result); + auto vr = vkGetMemoryFdKHR(al_info.device, &handle_info, &handle); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); } return handle; } diff --git a/wisdom/platform/wisdom/wisdom_platform.h b/wisdom/platform/wisdom/wisdom_platform.hpp similarity index 60% rename from wisdom/platform/wisdom/wisdom_platform.h rename to wisdom/platform/wisdom/wisdom_platform.hpp index cf9ae5c2..44536016 100644 --- a/wisdom/platform/wisdom/wisdom_platform.h +++ b/wisdom/platform/wisdom/wisdom_platform.hpp @@ -2,19 +2,19 @@ #define WISDOM_PLATFORM_H #ifdef WIS_WINDOWS_PLATFORM -#include +#include #else -#include +#include #endif #ifdef WIS_XCB_PLATFORM -#include +#include #endif // WIS_XCB_PLATFORM #ifdef WIS_X11_PLATFORM -#include +#include #endif // WIS_X11_PLATFORM #ifdef WIS_WAYLAND_PLATFORM -#include +#include #endif // WIS_WAYLAND_PLATFORM #endif // WISDOM_PLATFORM_H diff --git a/wisdom/platform/x11/CMakeLists.txt b/wisdom/platform/x11/CMakeLists.txt index 5872935c..317d14a2 100644 --- a/wisdom/platform/x11/CMakeLists.txt +++ b/wisdom/platform/x11/CMakeLists.txt @@ -13,7 +13,7 @@ target_include_directories( $) if(WISDOM_BUILD_BINARIES) - add_library(wisdom-x11 STATIC "wisdom/wisdom_x11.h" "wisdom/wisdom_x11.cpp") + add_library(wisdom-x11 STATIC "wisdom/wisdom_x11.hpp" "wisdom/wisdom_x11.cpp") add_library(wis::x11 ALIAS wisdom-x11) target_link_libraries(wisdom-x11 PUBLIC wis::wisdom) target_compile_definitions(wisdom-x11 PUBLIC WIS_X11_PLATFORM=1) diff --git a/wisdom/platform/x11/wisdom/wisdom_x11.cpp b/wisdom/platform/x11/wisdom/wisdom_x11.cpp index 0c7b0469..6c7b5588 100644 --- a/wisdom/platform/x11/wisdom/wisdom_x11.cpp +++ b/wisdom/platform/x11/wisdom/wisdom_x11.cpp @@ -1,11 +1,11 @@ #ifndef WISDOM_X11_CPP #define WISDOM_X11_CPP -#include +#include #include #include -wis::ResultValue -wis::platform::X11Extension::CreateSwapchain(const wis::VKDevice& device, wis::VKQueueView main_queue, const wis::SwapchainDesc* desc, Display* display, Window window) const noexcept +wis::VKSwapChain +wis::platform::X11Extension::CreateSwapchain(wis::Result& result, const wis::VKDevice& device, wis::VKQueueView main_queue, const wis::SwapchainDesc* desc, Display* display, Window window) const noexcept { VkXlibSurfaceCreateInfoKHR surface_desc{ .sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, @@ -19,11 +19,12 @@ wis::platform::X11Extension::CreateSwapchain(const wis::VKDevice& device, wis::V auto& devicei = device.GetInternal(); const auto& instance_table = instance.table(); VkSurfaceKHR surface; - auto result = vkCreateXlibSurfaceKHR(instance.get(), &surface_desc, nullptr, &surface); - if (!wis::succeeded(result)) { - return wis::make_result(result); + auto vr = vkCreateXlibSurfaceKHR(instance.get(), &surface_desc, nullptr, &surface); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return {}; } - return device.VKCreateSwapChain(wis::SharedSurface{ surface, instance, instance_table.vkDestroySurfaceKHR }, desc, std::get<0>(main_queue)); + return device.VKCreateSwapChain(result, wis::SharedSurface{ surface, instance, instance_table.vkDestroySurfaceKHR }, desc, std::get<0>(main_queue)); } #endif // WISDOM_XCB_CPP diff --git a/wisdom/platform/x11/wisdom/wisdom_x11.h b/wisdom/platform/x11/wisdom/wisdom_x11.hpp similarity index 75% rename from wisdom/platform/x11/wisdom/wisdom_x11.h rename to wisdom/platform/x11/wisdom/wisdom_x11.hpp index ff55a564..cc74d142 100644 --- a/wisdom/platform/x11/wisdom/wisdom_x11.h +++ b/wisdom/platform/x11/wisdom/wisdom_x11.hpp @@ -52,8 +52,15 @@ class X11Extension : public QueryInternalExtension - CreateSwapchain(const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, Display* display, Window window) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKSwapChain + CreateSwapchain(wis::Result& result, const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, Display* display, Window window) const noexcept; + + [[nodiscard]] inline wis::ResultValue + CreateSwapchain(const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, Display* display, Window window) const noexcept + { + auto fptr = static_cast(&X11Extension::CreateSwapchain); + return wis::ResultValue::from_member_func(fptr, this, device, main_queue, desc, display, window); + } }; } // namespace platform } // namespace wis diff --git a/wisdom/platform/xcb/CMakeLists.txt b/wisdom/platform/xcb/CMakeLists.txt index 38819d34..77894ebf 100644 --- a/wisdom/platform/xcb/CMakeLists.txt +++ b/wisdom/platform/xcb/CMakeLists.txt @@ -13,7 +13,7 @@ target_include_directories( $) if(WISDOM_BUILD_BINARIES) - add_library(wisdom-xcb STATIC "wisdom/wisdom_xcb.h" "wisdom/wisdom_xcb.cpp") + add_library(wisdom-xcb STATIC "wisdom/wisdom_xcb.hpp" "wisdom/wisdom_xcb.cpp") add_library(wis::xcb ALIAS wisdom-xcb) target_link_libraries(wisdom-xcb PUBLIC wis::wisdom) target_compile_definitions(wisdom-xcb PUBLIC WIS_XCB_PLATFORM=1) @@ -48,10 +48,8 @@ configure_package_config_file( "${CMAKE_CURRENT_BINARY_DIR}/wisdom-xcb-config.cmake" INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wisdom) -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/wisdom-xcb-config.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/wisdom") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/wisdom-xcb-config.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/wisdom") -install( - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wisdom/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wisdom) +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wisdom/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/wisdom) diff --git a/wisdom/platform/xcb/wisdom/wisdom_xcb.cpp b/wisdom/platform/xcb/wisdom/wisdom_xcb.cpp index 3d351613..6ae34180 100644 --- a/wisdom/platform/xcb/wisdom/wisdom_xcb.cpp +++ b/wisdom/platform/xcb/wisdom/wisdom_xcb.cpp @@ -1,11 +1,11 @@ #ifndef WISDOM_XCB_CPP #define WISDOM_XCB_CPP -#include +#include #include #include -wis::ResultValue -wis::platform::XCBExtension::CreateSwapchain(const wis::VKDevice& device, wis::VKQueueView main_queue, const wis::SwapchainDesc* desc, xcb_connection_t* connection, xcb_window_t window) const noexcept +wis::VKSwapChain +wis::platform::XCBExtension::CreateSwapchain(wis::Result& result, const wis::VKDevice& device, wis::VKQueueView main_queue, const wis::SwapchainDesc* desc, xcb_connection_t* connection, xcb_window_t window) const noexcept { VkXcbSurfaceCreateInfoKHR surface_desc{ .sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, @@ -19,11 +19,12 @@ wis::platform::XCBExtension::CreateSwapchain(const wis::VKDevice& device, wis::V auto& devicei = device.GetInternal(); const auto& instance_table = instance.table(); VkSurfaceKHR surface; - auto result = vkCreateXcbSurfaceKHR(instance.get(), &surface_desc, nullptr, &surface); - if (!wis::succeeded(result)) { - return wis::make_result(result); + auto vr = vkCreateXcbSurfaceKHR(instance.get(), &surface_desc, nullptr, &surface); + if (!wis::succeeded(vr)) { + result = wis::make_result(vr); + return {}; } - return device.VKCreateSwapChain(wis::SharedSurface{ surface, instance, instance_table.vkDestroySurfaceKHR }, desc, std::get<0>(main_queue)); + return device.VKCreateSwapChain(result, wis::SharedSurface{ surface, instance, instance_table.vkDestroySurfaceKHR }, desc, std::get<0>(main_queue)); } #endif // WISDOM_XCB_CPP diff --git a/wisdom/platform/xcb/wisdom/wisdom_xcb.h b/wisdom/platform/xcb/wisdom/wisdom_xcb.hpp similarity index 71% rename from wisdom/platform/xcb/wisdom/wisdom_xcb.h rename to wisdom/platform/xcb/wisdom/wisdom_xcb.hpp index f33661f7..53af02af 100644 --- a/wisdom/platform/xcb/wisdom/wisdom_xcb.h +++ b/wisdom/platform/xcb/wisdom/wisdom_xcb.hpp @@ -44,8 +44,15 @@ class XCBExtension : public QueryInternalExtension - CreateSwapchain(const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, xcb_connection_t* connection, xcb_window_t window) const noexcept; + [[nodiscard]] WIS_INLINE wis::VKSwapChain + CreateSwapchain(wis::Result& result, const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, xcb_connection_t* connection, xcb_window_t window) const noexcept; + + [[nodiscard]] inline wis::ResultValue + CreateSwapchain(const VKDevice& device, VKQueueView main_queue, const wis::SwapchainDesc* desc, xcb_connection_t* connection, xcb_window_t window) const noexcept + { + auto fptr = static_cast(&platform::XCBExtension::CreateSwapchain); + return wis::ResultValue::from_member_func(fptr, this, device, main_queue, desc, connection, window); + } }; } // namespace platform } // namespace wis diff --git a/xml/wis.xml b/xml/wis.xml index 151f5227..1cdff94c 100644 --- a/xml/wis.xml +++ b/xml/wis.xml @@ -145,7 +145,7 @@ Default is {MutiWaitFlags::All}"/> - + @@ -190,7 +190,7 @@ nullptr means allocate 1 space for each."/> - + - - + @@ -214,7 +214,13 @@ Does not work with 3D textures."/> - + + + + + + @@ -243,6 +249,18 @@ Equivalent to creating a Texture, allocating a memory and binding texture to it. + + + + + + + + + + @@ -326,7 +344,7 @@ Note, the resulting Texture must be destroyed before Memory backing it up."> - + @@ -352,7 +370,7 @@ Note, the resulting Texture must be destroyed before Memory backing it up."> - + @@ -364,7 +382,7 @@ Note, the resulting Texture must be destroyed before Memory backing it up."> - + @@ -417,7 +435,7 @@ Requires {DeviceFeature::AdvancedIndexBuffer} to be supported."> - + @@ -426,7 +444,7 @@ Requires {DeviceFeature::AdvancedIndexBuffer} to be supported."> - + - + @@ -652,7 +670,7 @@ The presence of core functionality is checked by the query function."/> - + + + + + + + + + + + + + + + + + + + + + + + + + +