diff options
| author | Quentin LADEVIE <qladevie@wanadev.fr> | 2025-01-26 22:27:10 +0100 |
|---|---|---|
| committer | Quentin LADEVIE <qladevie@wanadev.fr> | 2025-01-26 22:27:10 +0100 |
| commit | c29105b461135f3909cca0308fb05715cee45763 (patch) | |
| tree | 49c6c41bb88377f6af73ebdf39821038b88b05cf /api-test | |
| parent | 3490db941ea16e67da72f60ebda75ec0f8bb8051 (diff) | |
DX12 command buffers and resourcesapi-proto
Diffstat (limited to 'api-test')
| -rw-r--r-- | api-test/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | api-test/dx12-command-buffer.cpp | 47 | ||||
| -rw-r--r-- | api-test/dx12-device.cpp | 278 | ||||
| -rw-r--r-- | api-test/main.cpp | 246 | ||||
| -rw-r--r-- | api-test/vk-command-buffer.cpp (renamed from api-test/command-buffer.cpp) | 4 | ||||
| -rw-r--r-- | api-test/vk-device.cpp | 4 |
6 files changed, 439 insertions, 144 deletions
diff --git a/api-test/CMakeLists.txt b/api-test/CMakeLists.txt index 846b0fd..d8ae739 100644 --- a/api-test/CMakeLists.txt +++ b/api-test/CMakeLists.txt @@ -2,10 +2,12 @@ add_executable( api-test main.cpp vk-device.cpp - command-buffer.cpp + vk-command-buffer.cpp vk-bindless.cpp vk-utils.cpp dx12-device.cpp + dx12-command-buffer.cpp + ${CMAKE_SOURCE_DIR}/thirdparty/D3D12MemAlloc.cpp ${CMAKE_SOURCE_DIR}/src/window.cpp ${CMAKE_SOURCE_DIR}/src/utils.cpp ${CMAKE_SOURCE_DIR}/src/vulkan-loader.cpp diff --git a/api-test/dx12-command-buffer.cpp b/api-test/dx12-command-buffer.cpp new file mode 100644 index 0000000..0310dfd --- /dev/null +++ b/api-test/dx12-command-buffer.cpp @@ -0,0 +1,47 @@ +#include "dx12-command-buffer.hpp" + +#include "dx12-device.hpp" + +namespace dx12 { + void command_buffer::start() const { + HRESULT hr = command_allocator->Reset(); + assert(hr == S_OK); + + hr = dx12_command_buffer->Reset(command_allocator, nullptr); + assert(hr == S_OK); + + auto& device = dx12::device::get_render_device(); + dx12_command_buffer->SetDescriptorHeaps(2U, dx12::device::get_bindless_model().get_heaps()); + } + + void command_buffer::stop() const { + HRESULT hr = dx12_command_buffer->Close(); + assert(hr == S_OK); + } + + void command_buffer::copy(handle<device_buffer> src_buffer, handle<device_texture> dst_texture, uint64_t offset) const { + auto& dst = device::get_render_device().get_texture(dst_texture); + D3D12_TEXTURE_COPY_LOCATION dst_copy_location { + .pResource = dst.resource, + .Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, + .SubresourceIndex = 0U, + }; + + auto& src = device::get_render_device().get_buffer(src_buffer); + D3D12_TEXTURE_COPY_LOCATION src_copy_location { + .pResource = src.resource, + .Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, + .PlacedFootprint = { + .Offset = offset, + .Footprint = { + .Format = dst.format, + .Width = dst.width, + .Height = dst.height, + .Depth = dst.depth, + .RowPitch = static_cast<UINT>(dst.row_pitch), + }, + }, + }; + dx12_command_buffer->CopyTextureRegion(&dst_copy_location, 0U, 0U, 0U, &src_copy_location, nullptr); + } +} diff --git a/api-test/dx12-device.cpp b/api-test/dx12-device.cpp index e603fef..ac328ed 100644 --- a/api-test/dx12-device.cpp +++ b/api-test/dx12-device.cpp @@ -3,69 +3,237 @@ #include <cstdint> #include <cstdio> -dx12device dx12device::render_device = dx12device(); +#include "dx12-command-buffer.hpp" -void dx12device::init() { - SUCCEEDED(CreateDXGIFactory(IID_PPV_ARGS(&factory))); +namespace dx12 { + device device::render_device = dx12::device(); - uint32_t index = 0U; - while (factory->EnumAdapters(index, &adapter) != DXGI_ERROR_NOT_FOUND) { - DXGI_ADAPTER_DESC desc; - SUCCEEDED(adapter->GetDesc(&desc)); - printf("%S\n", desc.Description); - index++; + void device::init() { + HRESULT hr = S_OK; + hr = CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(&factory)); + assert(hr == S_OK); + + uint32_t index = 0U; + while (factory->EnumAdapters(index, &adapter) != DXGI_ERROR_NOT_FOUND) { + DXGI_ADAPTER_DESC desc; + SUCCEEDED(adapter->GetDesc(&desc)); + printf("%S\n", desc.Description); + index++; + } + + SUCCEEDED(factory->EnumAdapters(0U, &adapter)); + + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debug_interface)))) { + debug_interface->EnableDebugLayer(); + } + + hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(&device)); + assert(hr == S_OK); + + queues[static_cast<uint32_t>(QueueType::GRAPHICS)].type = D3D12_COMMAND_LIST_TYPE_DIRECT; + D3D12_COMMAND_QUEUE_DESC queue_desc{ + .Type = queues[static_cast<uint32_t>(QueueType::GRAPHICS)].type, + .Priority = D3D12_COMMAND_QUEUE_PRIORITY::D3D12_COMMAND_QUEUE_PRIORITY_HIGH, + .Flags = D3D12_COMMAND_QUEUE_FLAGS::D3D12_COMMAND_QUEUE_FLAG_NONE, + .NodeMask = 0U, + }; + device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&queues[static_cast<uint32_t>(QueueType::GRAPHICS)].dx_queue)); + assert(hr == S_OK); + + queue_desc.Type = queues[static_cast<uint32_t>(QueueType::ASYNC_COMPUTE)].type = D3D12_COMMAND_LIST_TYPE_COMPUTE; + queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY::D3D12_COMMAND_QUEUE_PRIORITY_HIGH, + device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&queues[static_cast<uint32_t>(QueueType::ASYNC_COMPUTE)].dx_queue)); + assert(hr == S_OK); + + queue_desc.Type = queues[static_cast<uint32_t>(QueueType::TRANSFER)].type = D3D12_COMMAND_LIST_TYPE_COPY; + queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY::D3D12_COMMAND_QUEUE_PRIORITY_HIGH, + device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&queues[static_cast<uint32_t>(QueueType::TRANSFER)].dx_queue)); + assert(hr == S_OK); + + hr = device->CreateFence(0U, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); + assert(hr == S_OK); + + D3D12MA::ALLOCATOR_DESC allocator_desc { + .pDevice = device, + .pAdapter = adapter, + }; + + hr = D3D12MA::CreateAllocator(&allocator_desc, &allocator); + assert(hr == S_OK); + + model.init(); } - SUCCEEDED(factory->EnumAdapters(0U, &adapter)); + handle<device_surface> device::create_surface(const surface_desc& desc) { + device_surface surface { + }; + DXGI_SAMPLE_DESC sample_desc{ + .Count = 1U, + .Quality = 0U, + }; + DXGI_SWAP_CHAIN_DESC1 swapchain_desc1{ + .Width = 0U, + .Height = 0U, + .Format = desc.surface_format, + .Stereo = FALSE, + .SampleDesc = sample_desc, + .BufferUsage = desc.usages, + .BufferCount = desc.image_count, + .Scaling = DXGI_SCALING_NONE, + .SwapEffect = desc.present_mode, + .AlphaMode = DXGI_ALPHA_MODE_IGNORE, + .Flags = 0U, + }; + HRESULT hr = factory->CreateSwapChainForHwnd(queues[static_cast<uint32_t>(QueueType::GRAPHICS)].dx_queue, desc.window_handle, &swapchain_desc1, nullptr, nullptr, &surface.swapchain); + assert(hr == S_OK); - SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_12_0, IID_PPV_ARGS(&device))); + return surfaces.add(surface); + } - D3D12_COMMAND_QUEUE_DESC queue_desc{ - .Type = D3D12_COMMAND_LIST_TYPE::D3D12_COMMAND_LIST_TYPE_DIRECT, - .Priority = D3D12_COMMAND_QUEUE_PRIORITY::D3D12_COMMAND_QUEUE_PRIORITY_HIGH, - .Flags = D3D12_COMMAND_QUEUE_FLAGS::D3D12_COMMAND_QUEUE_FLAG_NONE, - .NodeMask = 0U, - }; - SUCCEEDED(device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&queues[0U].dx_queue))); + handle<device_buffer> device::create_buffer(const buffer_desc& desc) { + device_buffer buffer { + .size = desc.size, + }; - queue_desc.Type = D3D12_COMMAND_LIST_TYPE::D3D12_COMMAND_LIST_TYPE_COMPUTE; - queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY::D3D12_COMMAND_QUEUE_PRIORITY_HIGH, - SUCCEEDED(device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&queues[1U].dx_queue))); + DXGI_SAMPLE_DESC sample_desc { + .Count = 1U, + .Quality = 0U, + }; + D3D12_RESOURCE_DESC resource_desc { + .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER, + .Alignment = 0U, + .Width = buffer.size, + .Height = 1U, + .DepthOrArraySize = 1U, + .MipLevels = 1U, + .Format = DXGI_FORMAT_UNKNOWN, + .SampleDesc = sample_desc, + .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR, + .Flags = desc.usages, + }; + D3D12MA::ALLOCATION_DESC allocation_desc { + .HeapType = desc.heap_type, + }; + HRESULT hr = allocator->CreateResource(&allocation_desc, &resource_desc, desc.states, nullptr, &buffer.alloc, IID_PPV_ARGS(&buffer.resource)); + assert(hr == S_OK); - queue_desc.Type = D3D12_COMMAND_LIST_TYPE::D3D12_COMMAND_LIST_TYPE_COPY; - queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY::D3D12_COMMAND_QUEUE_PRIORITY_HIGH, - SUCCEEDED(device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&queues[2U].dx_queue))); -} + if (desc.map) { + hr = buffer.resource->Map(0U, nullptr, &buffer.mapped_ptr); + assert(hr == S_OK); + } + + return buffers.add(buffer); + } -handle<dx12::device_surface> dx12device::create_surface(const dx12::surface_desc& desc) { - dx12::device_surface surface { - }; - DXGI_MODE_DESC mode_desc{ - .Width = 0U, - .Height = 0U, - .RefreshRate = { - .Numerator = 1U, - .Denominator = 60U, - }, - .Format = desc.surface_format, - .ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED, - .Scaling = DXGI_MODE_SCALING_CENTERED, - }; - DXGI_SAMPLE_DESC sample_desc{ - .Count = 1U, - .Quality = 0U, - }; - DXGI_SWAP_CHAIN_DESC swapchain_desc{ - .BufferDesc = mode_desc, - .SampleDesc = sample_desc, - .BufferUsage = desc.usages, - .BufferCount = desc.image_count, - .OutputWindow = desc.window_handle, - .Windowed = TRUE, - .SwapEffect = desc.present_mode, - .Flags = 0U, - }; - HRESULT hr = factory->CreateSwapChain(queues[static_cast<uint32_t>(dx12::QueueType::GRAPHICS)].dx_queue, &swapchain_desc, &surface.swapchain); + handle<device_texture> device::create_texture(const texture_desc& desc) { + device_texture texture { + .width = desc.width, + .height = desc.height, + .depth = desc.depth, + .mips = desc.mips, + .format = desc.format, + }; - return surfaces.add(surface); + DXGI_SAMPLE_DESC sample_desc { + .Count = 1U, + .Quality = 0U, + }; + D3D12_RESOURCE_DESC resource_desc { + .Dimension = desc.type, + .Alignment = 0U, + .Width = texture.width, + .Height = texture.height, + .DepthOrArraySize = static_cast<uint16_t>(texture.depth), + .MipLevels = static_cast<uint16_t>(texture.mips), + .Format = desc.format, + .SampleDesc = sample_desc, + .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN, + .Flags = desc.usages, + }; + D3D12MA::ALLOCATION_DESC allocation_desc { + .HeapType = D3D12_HEAP_TYPE_DEFAULT, + }; + + HRESULT hr = allocator->CreateResource(&allocation_desc, &resource_desc, desc.states, nullptr, &texture.alloc, IID_PPV_ARGS(&texture.resource)); + assert(hr == S_OK); + + D3D12_PLACED_SUBRESOURCE_FOOTPRINT place_footprint; + UINT num_rows = 0U; + UINT64 total_bytes = 0U; + device->GetCopyableFootprints(&resource_desc, 0U, 1U, 0U, &place_footprint, &num_rows, &texture.row_pitch, &total_bytes); + + return textures.add(texture); + } + + void device::allocate_command_buffers(command_buffer* buffers, size_t count, QueueType type) { + HRESULT hr = S_OK; + for (uint32_t index = 0U; index < count; index++) { + buffers[index].queue_type = type; + + auto list_type = queues[static_cast<uint32_t>(type)].type; + hr = device->CreateCommandAllocator(list_type, IID_PPV_ARGS(&buffers[index].command_allocator)); + assert(hr == S_OK); + + hr = device->CreateCommandList(0U, list_type, buffers[index].command_allocator, nullptr, IID_PPV_ARGS(&buffers[index].dx12_command_buffer)); + assert(hr == S_OK); + + hr = buffers[index].dx12_command_buffer->Close(); + assert(hr == S_OK); + } + } + + uint32_t device::submit(command_buffer* buffers, uint32_t count) { + assert((max_submitable_command_buffers - count) >= 0); + const auto queue_type = buffers[0].queue_type; + auto& queue = queues[static_cast<uint32_t>(buffers[0].queue_type)]; + ID3D12CommandList* lists[max_submitable_command_buffers] = { nullptr }; + + for (auto index{ 0U }; index < count; index++) { + assert(queue_type == buffers[index].queue_type); + + lists[index] = buffers[index].dx12_command_buffer; + } + + queue.dx_queue->ExecuteCommandLists(count, lists); + HRESULT hr = queue.dx_queue->Signal(fence, ++fence_value); + assert(hr == S_OK); + + for (uint32_t index = 0U; index < count; index++) { + auto& buffer = buffers[index]; + + hr = buffer.dx12_command_buffer->Reset(buffer.command_allocator, nullptr); + assert(hr == S_OK); + } + + return fence_value; + } + + void device::wait() { + for (auto& queue : queues) { + queue.dx_queue->Wait(fence, fence_value); + } + } + + void device::bindless_model::init() { + ID3D12Device* device = device::get_render_device().get_device(); + + D3D12_DESCRIPTOR_HEAP_DESC resources_descriptor_heap_desc { + .Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, + .NumDescriptors = D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_2, + .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + .NodeMask = 0U, + }; + + HRESULT hr = device->CreateDescriptorHeap(&resources_descriptor_heap_desc, IID_PPV_ARGS(&resources_heap)); + assert(hr == S_OK); + + D3D12_DESCRIPTOR_HEAP_DESC samplers_descriptor_heap_desc { + .Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, + .NumDescriptors = D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE, + .Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, + .NodeMask = 0U, + }; + hr = device->CreateDescriptorHeap(&samplers_descriptor_heap_desc, IID_PPV_ARGS(&samplers_heap)); + assert(hr == S_OK); + } } diff --git a/api-test/main.cpp b/api-test/main.cpp index f61fa13..e1c5af6 100644 --- a/api-test/main.cpp +++ b/api-test/main.cpp @@ -2,7 +2,9 @@ #include <cstdio> #include <array> #include <chrono> -#include <vk_mem_alloc.h> + +#include <Windows.h> +#include <debugapi.h> #define STB_IMAGE_IMPLEMENTATION #include <stb_image.h> @@ -14,9 +16,11 @@ #include "utils.hpp" #ifdef VK +#include <vk_mem_alloc.h> #include "vk-device.hpp" #else #include "dx12-device.hpp" +#include "dx12-command-buffer.hpp" #endif struct device_texture; @@ -64,22 +68,22 @@ void ui(uint32_t frame_time) { ImGui::Render(); } -void update_buffers(ImDrawData* draw_data, const device_buffer& vertex_buffer, const device_buffer& index_buffer) { - off_t vertex_offset = 0; - off_t index_offset = 0; - for (auto index {0} ; index < draw_data->CmdListsCount; index++) { - auto* cmd_list = draw_data->CmdLists[index]; - - size_t vertex_bytes_size = sizeof(ImDrawVert) * cmd_list->VtxBuffer.size(); - auto* vtx_ptr = static_cast<uint8_t*>(vertex_buffer.mapped_ptr) + vertex_offset; - memcpy(vtx_ptr, cmd_list->VtxBuffer.Data, vertex_bytes_size); - vertex_offset += static_cast<off_t>(vertex_bytes_size); - - size_t index_bytes_size = sizeof(ImDrawIdx) * cmd_list->IdxBuffer.size(); - memcpy(static_cast<uint8_t*>(index_buffer.mapped_ptr) + index_offset, cmd_list->IdxBuffer.Data, index_bytes_size); - index_offset += static_cast<off_t>(index_bytes_size); - } -} +// void update_buffers(ImDrawData* draw_data, const device_buffer& vertex_buffer, const device_buffer& index_buffer) { +// off_t vertex_offset = 0; +// off_t index_offset = 0; +// for (auto index {0} ; index < draw_data->CmdListsCount; index++) { +// auto* cmd_list = draw_data->CmdLists[index]; +// +// size_t vertex_bytes_size = sizeof(ImDrawVert) * cmd_list->VtxBuffer.size(); +// auto* vtx_ptr = static_cast<uint8_t*>(vertex_buffer.mapped_ptr) + vertex_offset; +// memcpy(vtx_ptr, cmd_list->VtxBuffer.Data, vertex_bytes_size); +// vertex_offset += static_cast<off_t>(vertex_bytes_size); +// +// size_t index_bytes_size = sizeof(ImDrawIdx) * cmd_list->IdxBuffer.size(); +// memcpy(static_cast<uint8_t*>(index_buffer.mapped_ptr) + index_offset, cmd_list->IdxBuffer.Data, index_bytes_size); +// index_offset += static_cast<off_t>(index_bytes_size); +// } +// } int main() { @@ -110,80 +114,105 @@ int main() { #ifdef VK auto& device = vkdevice::get_render_device(); #else - auto& device = dx12device::get_render_device(); + auto& device = dx12::device::get_render_device(); #endif device.init(); // auto main_scene = scene(camera(position, target, v_fov, aspect_ratio, aperture, focus_distance), window_width, window_height); -#ifdef VK auto surface_handle = device.create_surface({ .window_handle = wnd.handle, +#ifdef VK .surface_format = { .format = VK_FORMAT_B8G8R8A8_UNORM, .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, }, .present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR, .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_STORAGE_BIT, - }); #else - auto surface_handle = device.create_surface({ - .window_handle = wnd.handle, - .surface_format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + .surface_format = DXGI_FORMAT_R16G16B16A16_FLOAT, .present_mode = DXGI_SWAP_EFFECT_FLIP_DISCARD, - .usages = DXGI_USAGE_UNORDERED_ACCESS | DXGI_USAGE_RENDER_TARGET_OUTPUT, - }); + .usages = DXGI_USAGE_RENDER_TARGET_OUTPUT, #endif + }); auto& surface = device.get_surface(surface_handle); -#ifdef VK constexpr size_t image_size = 1024U; constexpr size_t image_count = 4U; auto staging_buffer_handle = device.create_buffer({ .size = image_size * image_size * sizeof(uint32_t) * image_count, +#ifdef VK .usages = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, +#else + + .map = true, + .states = D3D12_RESOURCE_STATE_COPY_SOURCE, + .usages = D3D12_RESOURCE_FLAG_NONE, + .heap_type = D3D12_HEAP_TYPE_UPLOAD, +#endif }); const auto& staging_buffer = device.get_buffer(staging_buffer_handle); // API test code - // int width; - // int height; - // int channels; - // uint8_t* data = stbi_load("../models/sponza/466164707995436622.jpg", &width, &height, &channels, 4); - // size_t size = static_cast<size_t>(width) * height * 4U; - // memcpy(staging_buffer.mapped_ptr, data, size); + int width; + int height; + int channels; + uint8_t* data = stbi_load("../models/sponza/466164707995436622.jpg", &width, &height, &channels, 4); + size_t size = static_cast<size_t>(width) * height * 4U; + memcpy(staging_buffer.mapped_ptr, data, size); - // auto gpu_texture_handle = device.create_texture({ - // .width = static_cast<uint32_t>(width), - // .height = static_cast<uint32_t>(height), - // .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - // .format = VK_FORMAT_R8G8B8A8_UNORM, - // .type = VK_IMAGE_TYPE_2D, - // }); + auto gpu_texture_handle = device.create_texture({ + .width = static_cast<uint32_t>(width), + .height = static_cast<uint32_t>(height), +#ifdef VK + .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + .format = VK_FORMAT_R8G8B8A8_UNORM, + .type = VK_IMAGE_TYPE_2D, +#else + .states = D3D12_RESOURCE_STATE_COPY_DEST, + .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, + .format = DXGI_FORMAT_R8G8B8A8_UNORM, + .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D, +#endif + }); - // off_t offset = width * height * 4; - // data = stbi_load("../models/sponza/715093869573992647.jpg", &width, &height, &channels, 4); - // size = static_cast<size_t>(width) * height * 4U; - // auto* addr = static_cast<void*>(static_cast<uint8_t*>(staging_buffer.mapped_ptr) + offset); - // memcpy(addr, data, size); + off_t offset = width * height * 4; + data = stbi_load("../models/sponza/715093869573992647.jpg", &width, &height, &channels, 4); + size = static_cast<size_t>(width) * height * 4U; + auto* addr = static_cast<void*>(static_cast<uint8_t*>(staging_buffer.mapped_ptr) + offset); + memcpy(addr, data, size); - // auto second_texture = device.create_texture({ - // .width = static_cast<uint32_t>(width), - // .height = static_cast<uint32_t>(height), - // .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT, - // .format = VK_FORMAT_R8G8B8A8_UNORM, - // .type = VK_IMAGE_TYPE_2D, - // }); + auto second_texture = device.create_texture({ + .width = static_cast<uint32_t>(width), + .height = static_cast<uint32_t>(height), +#ifdef VK + .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT, + .format = VK_FORMAT_R8G8B8A8_UNORM, + .type = VK_IMAGE_TYPE_2D, +#else + .states = D3D12_RESOURCE_STATE_COPY_DEST, + .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, + .format = DXGI_FORMAT_R8G8B8A8_UNORM, + .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D, +#endif + }); + + auto output_texture_handle = device.create_texture({ + .width = static_cast<uint32_t>(width), + .height = static_cast<uint32_t>(height), +#ifdef VK + .usages = VK_IMAGE_USAGE_STORAGE_BIT, + .format = VK_FORMAT_R8G8B8A8_UNORM, + .type = VK_IMAGE_TYPE_2D, +#else + .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, + .format = DXGI_FORMAT_R8G8B8A8_UNORM, + .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D, +#endif + }); - // auto output_texture_handle = device.create_texture({ - // .width = static_cast<uint32_t>(width), - // .height = static_cast<uint32_t>(height), - // .usages = VK_IMAGE_USAGE_STORAGE_BIT, - // .format = VK_FORMAT_R8G8B8A8_UNORM, - // .type = VK_IMAGE_TYPE_2D, - // }); uint8_t *pixels = nullptr; int atlas_width; @@ -192,9 +221,16 @@ int main() { const auto ui_texture_handle = device.create_texture({ .width = static_cast<uint32_t>(atlas_width), .height = static_cast<uint32_t>(atlas_height), +#ifdef VK .usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, .format = VK_FORMAT_R8G8B8A8_UNORM, .type = VK_IMAGE_TYPE_2D, +#else + .states = D3D12_RESOURCE_STATE_COPY_DEST, + .usages = D3D12_RESOURCE_FLAG_NONE, + .format = DXGI_FORMAT_R8G8B8A8_UNORM, + .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D, +#endif }); const auto& ui_texture = device.get_texture(ui_texture_handle); io.Fonts->SetTexID(*(void **)&ui_texture_handle.id); @@ -206,20 +242,27 @@ int main() { auto vertex_buffer_handle = device.create_buffer({ .size = Mb * sizeof(uint32_t), +#ifdef VK .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, +#else + #endif }); auto vertex_buffer = device.get_buffer(vertex_buffer_handle); auto index_buffer_handle = device.create_buffer({ .size = Mb * sizeof(uint32_t), +#ifdef VK .usages = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, .memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, .memory_usage = VMA_MEMORY_USAGE_CPU_TO_GPU, +#else +#endif }); auto index_buffer = device.get_buffer(index_buffer_handle); +#ifdef VK auto code = read_file("shaders/test.comp.spv"); auto compute = device.create_compute_pipeline({ .cs_code = code, @@ -233,24 +276,45 @@ int main() { auto tonemapping = device.create_compute_pipeline({ .cs_code = tonemapping_code, }); +#endif const auto acc_handle = device.create_texture({ .width = static_cast<uint32_t>(window_width), .height = static_cast<uint32_t>(window_height), +#ifdef VK .usages = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .type = VK_IMAGE_TYPE_2D, +#else + .states = D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, + .format = DXGI_FORMAT_R32G32B32A32_FLOAT, + .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D, +#endif }); + +#ifdef VK auto acc_storage_index = device.get_texture(acc_handle).get_storage_index(); +#endif const auto result_handle = device.create_texture({ .width = static_cast<uint32_t>(window_width), .height = static_cast<uint32_t>(window_height), +#ifdef VK .usages = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .type = VK_IMAGE_TYPE_2D, +#else + .states = D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + .usages = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, + .format = DXGI_FORMAT_R32G32B32A32_FLOAT, + .type = D3D12_RESOURCE_DIMENSION_TEXTURE2D, +#endif }); +#ifdef VK auto result_storage_index = device.get_texture(result_handle).get_storage_index(); +#endif +#ifdef VK std::array<VkFormat, 1U> formats { surface.surface_format.format }; auto vertex_code = read_file("shaders/api-test-ui.vert.spv"); auto fragment_code = read_file("shaders/api-test-ui.frag.spv"); @@ -259,47 +323,58 @@ int main() { .fs_code = fragment_code, .color_attachments_format = formats }); +#endif +#ifdef VK std::array<graphics_command_buffer, 4U> graphics_command_buffers; device.allocate_command_buffers(graphics_command_buffers.data(), graphics_command_buffers.size(), QueueType::GRAPHICS); +#else + std::array<dx12::graphics_command_buffer, 4U> graphics_command_buffers; + device.allocate_command_buffers(graphics_command_buffers.data(), graphics_command_buffers.size(), dx12::QueueType::GRAPHICS); +#endif // API test code - // RD_START_CAPTURE; + RD_START_CAPTURE; - // graphics_command_buffers[0].start(); + graphics_command_buffers[0].start(); - // graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - // graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - // graphics_command_buffers[0].barrier(ui_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - // graphics_command_buffers[0].copy(staging_buffer_handle, gpu_texture_handle); - // graphics_command_buffers[0].copy(staging_buffer_handle, second_texture, static_cast<VkDeviceSize>(offset)); - // graphics_command_buffers[0].copy(staging_buffer_handle, ui_texture_handle, static_cast<VkDeviceSize>(ui_offset)); +#ifdef VK + graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + graphics_command_buffers[0].barrier(ui_texture_handle, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); +#endif - // graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); - // graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); + graphics_command_buffers[0].copy(staging_buffer_handle, gpu_texture_handle); + graphics_command_buffers[0].copy(staging_buffer_handle, second_texture, offset); + graphics_command_buffers[0].copy(staging_buffer_handle, ui_texture_handle, ui_offset); +#ifdef VK + graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); + graphics_command_buffers[0].barrier(second_texture, VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); - // { - // graphics_command_buffers[0].dispatch({ - // .pipeline = compute, - // .group_size = { .vec = { image_size, image_size, 1U }}, - // .local_group_size = { .vec = { 8U, 8U, 1U }}, - // .params = { - // device.get_texture(second_texture).get_storage_index(), // Input 1 - // device.get_texture(gpu_texture_handle).get_storage_index(), // Input 2 - // device.get_texture(output_texture_handle).get_storage_index(), // Output - // }, - // }); - // } + { + graphics_command_buffers[0].dispatch({ + .pipeline = compute, + .group_size = { .vec = { image_size, image_size, 1U }}, + .local_group_size = { .vec = { 8U, 8U, 1U }}, + .params = { + device.get_texture(second_texture).get_storage_index(), // Input 1 + device.get_texture(gpu_texture_handle).get_storage_index(), // Input 2 + device.get_texture(output_texture_handle).get_storage_index(), // Output + }, + }); + } - // graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + graphics_command_buffers[0].barrier(gpu_texture_handle, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); +#endif - // graphics_command_buffers[0].stop(); + graphics_command_buffers[0].stop(); - // device.submit(graphics_command_buffers.data(), 1); - // device.wait(); + device.submit(graphics_command_buffers.data(), 1); + device.wait(); - // RD_END_CAPTURE; + RD_END_CAPTURE; +#ifdef VK std::array<handle<device_texture>, 1U> color_attachment {}; constexpr uint32_t virtual_frames_count = 2U; uint32_t frame_time = 1U; @@ -473,6 +548,7 @@ int main() { device.destroy_buffer(staging_buffer_handle); device.destroy_buffer(vertex_buffer_handle); device.destroy_buffer(index_buffer_handle); + device.deinit(); ImGui::DestroyContext(); #endif // VK diff --git a/api-test/command-buffer.cpp b/api-test/vk-command-buffer.cpp index d694f9f..bdb0e40 100644 --- a/api-test/command-buffer.cpp +++ b/api-test/vk-command-buffer.cpp @@ -1,4 +1,4 @@ -#include "command-buffer.hpp" +#include "vk-command-buffer.hpp" #include <vulkan/vulkan_core.h> @@ -82,7 +82,7 @@ void command_buffer::barrier(handle<device_texture> texture_handle, VkPipelineSt texture.access = access; } -void command_buffer::copy(handle<device_buffer> buffer_handle, ::handle<device_texture> texture_handle, VkDeviceSize offset) const { +void command_buffer::copy(handle<device_buffer> buffer_handle, ::handle<device_texture> texture_handle, uint64_t offset) const { auto& device = vkdevice::get_render_device(); const auto& buffer = device.get_buffer(buffer_handle); const auto& texture = device.get_texture(texture_handle); diff --git a/api-test/vk-device.cpp b/api-test/vk-device.cpp index 024b570..a3c5119 100644 --- a/api-test/vk-device.cpp +++ b/api-test/vk-device.cpp @@ -8,6 +8,7 @@ #include "vk-utils.hpp" #include "vulkan-loader.hpp" +#include "vk-command-buffer.hpp" vkdevice vkdevice::render_device = vkdevice(); @@ -44,7 +45,7 @@ void vkdevice::init() { timeline_semaphore = get_semaphore(semaphore); } -vkdevice::~vkdevice() { +void vkdevice::deinit() { vkDeviceWaitIdle(device); bindless_model::destroy_bindless_model(bindless); @@ -66,6 +67,7 @@ vkdevice::~vkdevice() { vkDestroyInstance(instance, nullptr); } + void vkdevice::wait() { vkDeviceWaitIdle(device); }; handle<device_texture> vkdevice::create_texture(const texture_desc& desc) { |
