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"
"d3d_texture.cpp"
"vulkan_texture.cpp"
"vulkan_platform.cpp"
)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
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}/"
)
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
@@ -44,24 +47,18 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
vulkan-1
)
#add_executable(${PROJECT_NAME}_test
# "main.cpp"
#)
add_executable(${PROJECT_NAME}_test
"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
# E:\\thermion\\thermion_dart\\native\\include\\vulkan
## 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_directories(${PROJECT_NAME}_test PRIVATE
"C:\\Users\\nickh\\Documents\\thermion\\thermion_dart\\.dart_tool\\thermion_dart\\lib\\v1.58.0\\windows\\debug"
)
#target_link_libraries(${PROJECT_NAME}_test PRIVATE
# ${PROJECT_NAME}
#)
target_link_libraries(${PROJECT_NAME}_test PRIVATE
${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) {
_D3D11Device->Release();
}
std::cerr << "D3DContext destroyed" << std::endl;
}
std::unique_ptr<D3DTexture> D3DContext::CreateTexture(uint32_t width, uint32_t height)
@@ -139,12 +140,10 @@ if (FAILED(hr)) {
// 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);
std::cout << "FLUSH RENDER TARGET" << std::endl;
Flush();
return texture;
}

View File

@@ -32,64 +32,66 @@ int main()
uint32_t width = 100;
uint32_t height = 100;
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;
ctx->DestroyRenderingSurface(handle);
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 "ThermionWin32.h"
#include <functional>
@@ -28,7 +26,15 @@ namespace thermion::windows::vulkan {
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();
// Create Vulkan instance
@@ -92,13 +98,13 @@ ThermionVulkanContext::ThermionVulkanContext() {
return;
}
_platform = new TVulkanPlatform();
_platform = std::make_unique<TVulkanPlatform>();
_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);
@@ -117,27 +123,40 @@ HANDLE ThermionVulkanContext::CreateRenderingSurface(uint32_t width, uint32_t he
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) {
_vulkanTextures.erase(std::remove_if(_vulkanTextures.begin(), _vulkanTextures.end(), [=](auto&& vkTexture) {
void DestroyRenderingSurface(HANDLE handle) {
std::cerr << "Destroying rendering surface " << handle << std::endl;
auto vulkanNewEnd = std::remove_if(_vulkanTextures.begin(), _vulkanTextures.end(), [=](auto&& vkTexture) {
return vkTexture->GetD3DTextureHandle() == handle;
}));
});
_d3dTextures.erase(std::remove_if(_d3dTextures.begin(), _d3dTextures.end(), [=](auto&& d3dTexture) {
return d3dTexture->GetTextureHandle() == handle;
}));
if (vulkanNewEnd != _vulkanTextures.end()) {
_vulkanTextures.erase(vulkanNewEnd, _vulkanTextures.end());
} else {
std::cerr << "Vulkan texture not found?" << std::endl;
}
void ThermionVulkanContext::Flush() {
auto d3dNewEnd = std::remove_if(_d3dTextures.begin(), _d3dTextures.end(), [=](auto&& d3dTexture) {
return d3dTexture->GetTextureHandle() == handle;
});
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
}
// Function to perform the blit operation
void ThermionVulkanContext::BlitFromSwapchain() {
void BlitFromSwapchain() {
std::lock_guard lock(_platform->mutex);
if(!_platform->current || _d3dTextures.size() == 0) {
@@ -317,11 +336,10 @@ void ThermionVulkanContext::BlitFromSwapchain() {
// bluevk::vkFreeCommandBuffers(device, commandPool, 1, &cmd);
}
void ThermionVulkanContext::readPixelsFromImage(
void readPixelsFromImage(
uint32_t width,
uint32_t height,
std::vector<uint8_t>& outPixels
) {
std::vector<uint8_t>& outPixels) {
auto&& vkTexture = _vulkanTextures.back();
auto image = vkTexture->GetImage();
@@ -508,4 +526,58 @@ void ThermionVulkanContext::readPixelsFromImage(
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;
}
}