update Windows Vulkan implementation

This commit is contained in:
Nick Fisher
2025-04-02 22:20:21 +08:00
parent 9d4fd4d6d4
commit a08cc7aa62
5 changed files with 676 additions and 548 deletions

View File

@@ -25,15 +25,18 @@ add_library(${PROJECT_NAME} SHARED
"utils.cpp" "utils.cpp"
"d3d_texture.cpp" "d3d_texture.cpp"
"vulkan_texture.cpp" "vulkan_texture.cpp"
"vulkan_platform.cpp"
) )
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
include_directories(${PROJECT_NAME} INTERFACE include_directories(${PROJECT_NAME} INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/../../include" "${CMAKE_CURRENT_SOURCE_DIR}/../../../include"
"${CMAKE_CURRENT_SOURCE_DIR}/../../../include/windows/vulkan"
"${CMAKE_CURRENT_SOURCE_DIR}/../../../include/filament/"
"${CMAKE_CURRENT_SOURCE_DIR}/" "${CMAKE_CURRENT_SOURCE_DIR}/"
) )
target_link_directories(${PROJECT_NAME} PRIVATE target_link_directories(${PROJECT_NAME} PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/../../../.dart_tool/thermion_dart/lib/v1.51.2/windows/debug "C:\\Users\\nickh\\Documents\\thermion\\thermion_dart\\.dart_tool\\thermion_dart\\lib\\v1.58.0\\windows\\debug"
) )
target_link_libraries(${PROJECT_NAME} PRIVATE target_link_libraries(${PROJECT_NAME} PRIVATE
@@ -44,24 +47,18 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
vulkan-1 vulkan-1
) )
#add_executable(${PROJECT_NAME}_test add_executable(${PROJECT_NAME}_test
# "main.cpp" "main.cpp"
#) )
#target_compile_features(${PROJECT_NAME}_test PUBLIC cxx_std_20) target_compile_features(${PROJECT_NAME}_test PUBLIC cxx_std_20)
#target_include_directories(${PROJECT_NAME}_test PRIVATE target_link_directories(${PROJECT_NAME}_test PRIVATE
# E:\\thermion\\thermion_dart\\native\\include\\vulkan "C:\\Users\\nickh\\Documents\\thermion\\thermion_dart\\.dart_tool\\thermion_dart\\lib\\v1.58.0\\windows\\debug"
## E:\\thermion\\thermion_dart\\native\\include )
# E:\\thermion\\thermion_dart\\native\\include\\filament
#)
#target_link_directories(${PROJECT_NAME}_test PRIVATE
# E:\\thermion\\thermion_dart\\.dart_tool\\thermion_dart\\lib\\v1.51.2\\windows\\debug
# E:\\VulkanSDK\\1.3.296.0\\Lib
#)
#target_link_libraries(${PROJECT_NAME}_test PRIVATE target_link_libraries(${PROJECT_NAME}_test PRIVATE
# ${PROJECT_NAME} ${PROJECT_NAME}
#) )
#add_dependencies(${PROJECT_NAME}_test ${PROJECT_NAME}) add_dependencies(${PROJECT_NAME}_test ${PROJECT_NAME})

View File

@@ -75,6 +75,7 @@ namespace thermion::windows::d3d
if (_D3D11Device) { if (_D3D11Device) {
_D3D11Device->Release(); _D3D11Device->Release();
} }
std::cerr << "D3DContext destroyed" << std::endl;
} }
std::unique_ptr<D3DTexture> D3DContext::CreateTexture(uint32_t width, uint32_t height) std::unique_ptr<D3DTexture> D3DContext::CreateTexture(uint32_t width, uint32_t height)
@@ -128,24 +129,22 @@ namespace thermion::windows::d3d
auto texture = std::make_unique<D3DTexture>(_d3dTexture2D, _d3dTexture2DHandle, width, height); auto texture = std::make_unique<D3DTexture>(_d3dTexture2D, _d3dTexture2DHandle, width, height);
ID3D11RenderTargetView* rtv = nullptr; ID3D11RenderTargetView* rtv = nullptr;
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {}; D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
rtvDesc.Texture2D.MipSlice = 0; rtvDesc.Texture2D.MipSlice = 0;
hr = _D3D11Device->CreateRenderTargetView(_d3dTexture2D.Get(), &rtvDesc, &rtv); hr = _D3D11Device->CreateRenderTargetView(_d3dTexture2D.Get(), &rtvDesc, &rtv);
if (FAILED(hr)) { if (FAILED(hr)) {
std::cout << "Failed to create render target view" << std::endl; std::cout << "Failed to create render target view" << std::endl;
// return; // return;
} }
std::cout << "Created render target view" << std::endl; // Clear the texture to blue
float blueColor[4] = { 1.0f, 0.0f, 1.0f, 1.0f }; // RGBA
_D3D11DeviceContext->ClearRenderTargetView(rtv, blueColor);
// Clear the texture to blue Flush();
float blueColor[4] = { 1.0f, 0.0f, 1.0f, 1.0f }; // RGBA
_D3D11DeviceContext->ClearRenderTargetView(rtv, blueColor);
std::cout << "FLUSH RENDER TARGET" << std::endl;
Flush();
return texture; return texture;
} }

View File

@@ -32,64 +32,66 @@ int main()
uint32_t width = 100; uint32_t width = 100;
uint32_t height = 100; uint32_t height = 100;
auto handle = ctx->CreateRenderingSurface(width, height, 0, 0); auto handle = ctx->CreateRenderingSurface(width, height, 0, 0);
auto *engine = filament::Engine::create(filament::Engine::Backend::VULKAN, ctx->GetPlatform(), nullptr, nullptr);
auto *swapChain = engine->createSwapChain(width,height, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE | filament::SwapChain::CONFIG_HAS_STENCIL_BUFFER);
engine->flushAndWait();
if(engine->isValid(reinterpret_cast<filament::SwapChain*>(swapChain))) {
std::cout << "VALID SWAPCHIAN" << std::endl;
} else {
std::cout << "INVALID SWAPCHIAN" << std::endl;
}
auto renderer = engine->createRenderer();
filament::Renderer::ClearOptions clearOptions;
clearOptions.clear = true;
clearOptions.clearColor = { 0.0f, 1.0f, 0.0f, 1.0f };
renderer->setClearOptions(clearOptions);
auto scene = engine->createScene();
auto *view = engine->createView();
view->setViewport(filament::Viewport {0,0, width,height});
view->setBlendMode(filament::View::BlendMode::TRANSLUCENT);
view->setScene(scene);
auto camera = engine->createCamera(utils::EntityManager::get().create());
view->setCamera(camera);
engine->flushAndWait();
size_t pixelBufferSize = width * height * 4;
auto out = new uint8_t[pixelBufferSize];
auto pbd = filament::Texture::PixelBufferDescriptor(
out, pixelBufferSize,
filament::Texture::Format::RGBA,
filament::Texture::Type::UBYTE, nullptr, nullptr, nullptr);
renderer->beginFrame(swapChain);
renderer->render(view);
renderer->readPixels(0, 0, width, height, std::move(pbd));
renderer->endFrame();
engine->flushAndWait();
std::cout << "FLUSHED" << std::endl;
if(!SavePixelsAsBMP(out, width, height, width, "savepixels.bmp")) {
std::cout << "FAILED TO SAVE PIXELS" << std::endl;
}
std::cout << "SAVED PIXELS" << std::endl;
// ctx->GetTexture()->Flush();
ctx->BlitFromSwapchain();
std::vector<uint8_t> outPixels(width * height * 4);
ctx->readPixelsFromImage(width, height, outPixels);
std::cout << "READBACK FROM VULKAN COMPLETE " << std::endl;
SavePixelsAsBMP(outPixels.data(), width, height, width, "vulkan_readback.bmp");
std::cout << "CREATED" << std::endl; std::cout << "CREATED" << std::endl;
ctx->DestroyRenderingSurface(handle); ctx->DestroyRenderingSurface(handle);
std::cout << "FINISHED" << std::endl; std::cout << "FINISHED" << std::endl;
// auto *engine = filament::Engine::create(filament::Engine::Backend::VULKAN, ctx->GetPlatform(), nullptr, nullptr);
// auto *swapChain = engine->createSwapChain(width,height, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE | filament::SwapChain::CONFIG_HAS_STENCIL_BUFFER);
// engine->flushAndWait();
// if(engine->isValid(reinterpret_cast<filament::SwapChain*>(swapChain))) {
// std::cout << "VALID SWAPCHIAN" << std::endl;
// } else {
// std::cout << "INVALID SWAPCHIAN" << std::endl;
// }
// auto renderer = engine->createRenderer();
// filament::Renderer::ClearOptions clearOptions;
// clearOptions.clear = true;
// clearOptions.clearColor = { 1.0f, 0.0f, 0.5f, 1.0f };
// renderer->setClearOptions(clearOptions);
// auto scene = engine->createScene();
// auto *view = engine->createView();
// view->setViewport(filament::Viewport {0,0, width,height});
// view->setBlendMode(filament::View::BlendMode::TRANSLUCENT);
// view->setScene(scene);
// auto camera = engine->createCamera(utils::EntityManager::get().create());
// view->setCamera(camera);
// engine->flushAndWait();
// size_t pixelBufferSize = width * height * 4;
// auto out = new uint8_t[pixelBufferSize];
// auto pbd = filament::Texture::PixelBufferDescriptor(
// out, pixelBufferSize,
// filament::Texture::Format::RGBA,
// filament::Texture::Type::UBYTE, nullptr, nullptr, nullptr);
// renderer->beginFrame(swapChain);
// renderer->render(view);
// renderer->readPixels(0, 0, width, height, std::move(pbd));
// renderer->endFrame();
// engine->flushAndWait();
// std::cout << "FLUSHED" << std::endl;
// if(!SavePixelsAsBMP(out, width, height, width, "savepixels.bmp")) {
// std::cout << "FAILED TO SAVE PIXELS" << std::endl;
// }
// // ctx->GetTexture()->Flush();
// ctx->BlitFromSwapchain(width,height);
// ctx->GetTexture()->SaveToBMP("d3d_texture.bmp");
// std::vector<uint8_t> outPixels(width * height * 4);
// ctx->readPixelsFromImage(width, height, outPixels);
// std::cout << "READBACK FROM VULKAN COMPLETE " << std::endl;
// thermion::windows::d3d::D3DTexture::SavePixelsAsBMP(outPixels.data(), width, height, width, "vulkan_readback.bmp");
} }

View File

@@ -1,7 +1,5 @@
#define THERMION_WIN32_KHR_BUILD
#include "vulkan_context.h" #include "vulkan_context.h"
#include "ThermionWin32.h" #include "ThermionWin32.h"
#include <functional> #include <functional>
@@ -28,7 +26,15 @@ namespace thermion::windows::vulkan {
using namespace bluevk; using namespace bluevk;
ThermionVulkanContext::ThermionVulkanContext() { class ThermionVulkanContext::Impl {
public:
~Impl() {
std::cerr << "ThermionVulkanContext destructor " << _vulkanTextures.size() << " Vulkan textures / " << _d3dTextures.size() << " D3D textures remain" << std::endl;
_d3dContext = std::nullptr_t();
}
Impl() {
bluevk::initialize(); bluevk::initialize();
// Create Vulkan instance // Create Vulkan instance
@@ -92,13 +98,13 @@ ThermionVulkanContext::ThermionVulkanContext() {
return; return;
} }
_platform = new TVulkanPlatform(); _platform = std::make_unique<TVulkanPlatform>();
_d3dContext = std::make_unique<thermion::windows::d3d::D3DContext>(); _d3dContext = std::make_unique<thermion::windows::d3d::D3DContext>();
} }
HANDLE ThermionVulkanContext::CreateRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) { HANDLE CreateRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) {
Log("Creating Vulkan texture %dx%d", width, height); Log("Creating Vulkan texture %dx%d", width, height);
@@ -115,29 +121,42 @@ HANDLE ThermionVulkanContext::CreateRenderingSurface(uint32_t width, uint32_t he
_d3dTextures.push_back(std::move(d3dTexture)); _d3dTextures.push_back(std::move(d3dTexture));
_vulkanTextures.push_back(std::move(vkTexture)); _vulkanTextures.push_back(std::move(vkTexture));
return d3dTextureHandle; return d3dTextureHandle;
} }
void ThermionVulkanContext::ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) { void ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) {
} }
void ThermionVulkanContext::DestroyRenderingSurface(HANDLE handle) { void DestroyRenderingSurface(HANDLE handle) {
std::cerr << "Destroying rendering surface " << handle << std::endl;
_vulkanTextures.erase(std::remove_if(_vulkanTextures.begin(), _vulkanTextures.end(), [=](auto&& vkTexture) { auto vulkanNewEnd = std::remove_if(_vulkanTextures.begin(), _vulkanTextures.end(), [=](auto&& vkTexture) {
return vkTexture->GetD3DTextureHandle() == handle; return vkTexture->GetD3DTextureHandle() == handle;
})); });
_d3dTextures.erase(std::remove_if(_d3dTextures.begin(), _d3dTextures.end(), [=](auto&& d3dTexture) { if (vulkanNewEnd != _vulkanTextures.end()) {
_vulkanTextures.erase(vulkanNewEnd, _vulkanTextures.end());
} else {
std::cerr << "Vulkan texture not found?" << std::endl;
}
auto d3dNewEnd = std::remove_if(_d3dTextures.begin(), _d3dTextures.end(), [=](auto&& d3dTexture) {
return d3dTexture->GetTextureHandle() == handle; return d3dTexture->GetTextureHandle() == handle;
})); });
}
void ThermionVulkanContext::Flush() { if (d3dNewEnd != _d3dTextures.end()) {
_d3dTextures.erase(d3dNewEnd, _d3dTextures.end());
} else {
std::cerr << "D3D texture not found?" << std::endl;
}
std::cerr << "Rendering surface destroyed, " << _vulkanTextures.size() << " Vulkan textures / " << _d3dTextures.size() << " D3D textures remain" << std::endl;
}
void Flush() {
// ?? what to do here // ?? what to do here
} }
// Function to perform the blit operation void BlitFromSwapchain() {
void ThermionVulkanContext::BlitFromSwapchain() {
std::lock_guard lock(_platform->mutex); std::lock_guard lock(_platform->mutex);
if(!_platform->current || _d3dTextures.size() == 0) { if(!_platform->current || _d3dTextures.size() == 0) {
@@ -315,13 +334,12 @@ void ThermionVulkanContext::BlitFromSwapchain() {
// // Cleanup // // Cleanup
// bluevk::vkDestroyFence(device, fence, nullptr); // bluevk::vkDestroyFence(device, fence, nullptr);
// bluevk::vkFreeCommandBuffers(device, commandPool, 1, &cmd); // bluevk::vkFreeCommandBuffers(device, commandPool, 1, &cmd);
} }
void ThermionVulkanContext::readPixelsFromImage( void readPixelsFromImage(
uint32_t width, uint32_t width,
uint32_t height, uint32_t height,
std::vector<uint8_t>& outPixels std::vector<uint8_t>& outPixels) {
) {
auto&& vkTexture = _vulkanTextures.back(); auto&& vkTexture = _vulkanTextures.back();
auto image = vkTexture->GetImage(); auto image = vkTexture->GetImage();
@@ -506,6 +524,60 @@ void ThermionVulkanContext::readPixelsFromImage(
vkFreeMemory(device, stagingBufferMemory, nullptr); vkFreeMemory(device, stagingBufferMemory, nullptr);
std::cout << "Successfully completed readPixelsFromImage" << std::endl; std::cout << "Successfully completed readPixelsFromImage" << std::endl;
}
filament::backend::VulkanPlatform *GetPlatform() {
return _platform.get();
}
private:
VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
VkDevice device = VK_NULL_HANDLE;
VkCommandPool commandPool = VK_NULL_HANDLE;
VkQueue queue = VK_NULL_HANDLE;
std::unique_ptr<thermion::windows::d3d::D3DContext> _d3dContext;
std::vector<std::unique_ptr<thermion::windows::d3d::D3DTexture>> _d3dTextures;
std::vector<std::unique_ptr<thermion::windows::vulkan::VulkanTexture>> _vulkanTextures;
std::unique_ptr<TVulkanPlatform> _platform;
};
HANDLE ThermionVulkanContext::CreateRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) {
return pImpl->CreateRenderingSurface(width, height, left, top);
} }
void ThermionVulkanContext::DestroyRenderingSurface(HANDLE handle) {
pImpl->DestroyRenderingSurface(handle);
}
void ThermionVulkanContext::ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) {
pImpl->ResizeRenderingSurface(width, height, left, top);
}
void ThermionVulkanContext::Flush() {
pImpl->Flush();
}
filament::backend::VulkanPlatform *ThermionVulkanContext::GetPlatform() {
return pImpl->GetPlatform();
}
void ThermionVulkanContext::BlitFromSwapchain() {
pImpl->BlitFromSwapchain();
}
void ThermionVulkanContext::readPixelsFromImage(
uint32_t width,
uint32_t height,
std::vector<uint8_t>& outPixels
) {
pImpl->readPixelsFromImage(width, height, outPixels);
}
ThermionVulkanContext::ThermionVulkanContext() : pImpl(std::make_unique<ThermionVulkanContext::Impl>()) {}
ThermionVulkanContext::~ThermionVulkanContext() = default;
} }

View File

@@ -0,0 +1,58 @@
#include "vulkan_context.h"
#include "ThermionWin32.h"
#include <functional>
#include <vector>
#include <chrono>
#include <string>
#include <fstream>
#include <iostream>
#include <memory>
#include <thread>
#include "filament/backend/platforms/VulkanPlatform.h"
#include "filament/Engine.h"
#include "filament/Renderer.h"
#include "filament/View.h"
#include "filament/Viewport.h"
#include "filament/Scene.h"
#include "filament/SwapChain.h"
#include "filament/Texture.h"
#include "Log.hpp"
namespace thermion::windows::vulkan {
TVulkanPlatform::TVulkanPlatform() {
_customization.gpu.index = 0;
}
TVulkanPlatform::~TVulkanPlatform() {
std::cerr << "Destroyed Vulkan platform" << std::endl;
}
filament::backend::VulkanPlatform::Customization TVulkanPlatform::getCustomization() const noexcept {
return _customization;
}
filament::backend::VulkanPlatform::SwapChainPtr TVulkanPlatform::createSwapChain(void* nativeWindow, uint64_t flags,
VkExtent2D extent) {
std::lock_guard lock(mutex);
current = filament::backend::VulkanPlatform::createSwapChain(nativeWindow, flags, extent);
std::cerr << "Created swap chain with flags " << flags << std::endl;
return current;
}
void TVulkanPlatform::destroy(filament::backend::VulkanPlatform::SwapChainPtr handle) {
std::lock_guard lock(mutex);
current = nullptr;
std::cerr << "Destroyed swap chain" << std::endl;
}
VkResult TVulkanPlatform::present(SwapChainPtr handle, uint32_t index, VkSemaphore finishedDrawing) {
auto result = filament::backend::VulkanPlatform::present(handle, index, finishedDrawing);
currentColorIndex = index;
return result;
}
}