add first pass vulkan implementation
This commit is contained in:
@@ -0,0 +1,45 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
set(PROJECT_NAME "thermion_egl")
|
||||||
|
project(${PROJECT_NAME} LANGUAGES C CXX)
|
||||||
|
|
||||||
|
cmake_policy(VERSION 3.14...3.25)
|
||||||
|
|
||||||
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||||
|
set(BUILD_SHARED_LIBS TRUE)
|
||||||
|
set(CMAKE_ENABLE_EXPORTS TRUE)
|
||||||
|
|
||||||
|
add_definitions(-DVK_STATIC_DISPATCH)
|
||||||
|
|
||||||
|
add_library(${PROJECT_NAME} SHARED
|
||||||
|
"d3d_texture.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
|
||||||
|
include_directories(${PROJECT_NAME} INTERFACE
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/../../include"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||||
|
Shlwapi
|
||||||
|
dxgi
|
||||||
|
d3d11
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test executable
|
||||||
|
add_executable(${PROJECT_NAME}_test
|
||||||
|
"main.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${PROJECT_NAME}_test PRIVATE
|
||||||
|
E:\\VulkanSDK\\1.3.296.0\\Include
|
||||||
|
)
|
||||||
|
target_link_directories(${PROJECT_NAME}_test PRIVATE
|
||||||
|
E:\\VulkanSDK\\1.3.296.0\\Lib
|
||||||
|
)
|
||||||
|
target_link_libraries(${PROJECT_NAME}_test PRIVATE
|
||||||
|
${PROJECT_NAME}
|
||||||
|
vulkan-1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make sure the test depends on the library
|
||||||
|
add_dependencies(${PROJECT_NAME}_test ${PROJECT_NAME})
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
#include "d3d_texture.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace thermion::windows::d3d {
|
||||||
|
|
||||||
|
void D3DTexture::Flush() {
|
||||||
|
// glFlush(); // Ensure GL commands are completed
|
||||||
|
_D3D11DeviceContext->Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE D3DTexture::GetTextureHandle() {
|
||||||
|
return _d3dTexture2DHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DTexture::~D3DTexture() {
|
||||||
|
_d3dTexture2D->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNTHandleSupported(ID3D11Device* device) {
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11Device5> device5;
|
||||||
|
return SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&device5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DTexture::D3DTexture(
|
||||||
|
uint32_t width, uint32_t height,
|
||||||
|
std::function<void(size_t, size_t)> onResizeRequested
|
||||||
|
)
|
||||||
|
: _width(width), _height(height), _onResizeRequested(onResizeRequested) {
|
||||||
|
|
||||||
|
IDXGIAdapter *adapter_ = nullptr;
|
||||||
|
|
||||||
|
auto feature_levels = {
|
||||||
|
D3D_FEATURE_LEVEL_12_0,
|
||||||
|
D3D_FEATURE_LEVEL_11_1,
|
||||||
|
D3D_FEATURE_LEVEL_11_0,
|
||||||
|
D3D_FEATURE_LEVEL_10_1,
|
||||||
|
D3D_FEATURE_LEVEL_10_0,
|
||||||
|
D3D_FEATURE_LEVEL_9_3,
|
||||||
|
};
|
||||||
|
|
||||||
|
IDXGIFactory1 *dxgi = nullptr;
|
||||||
|
HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)&dxgi);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
std::cout << "Failed to create DXGI 1.1 factory" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dxgi->EnumAdapters(0, &adapter_);
|
||||||
|
dxgi->Release();
|
||||||
|
if (!adapter_) {
|
||||||
|
std::cout << "Failed to locate default D3D adapter" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<IDXGIFactory2> factory2;
|
||||||
|
if (SUCCEEDED(dxgi->QueryInterface(IID_PPV_ARGS(&factory2)))) {
|
||||||
|
std::cout << "DXGI 1.2 or higher supported" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_ADAPTER_DESC adapter_desc_;
|
||||||
|
adapter_->GetDesc(&adapter_desc_);
|
||||||
|
std::wcout << L"D3D adapter description: " << adapter_desc_.Description
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
hr = ::D3D11CreateDevice(
|
||||||
|
adapter_, D3D_DRIVER_TYPE_UNKNOWN, 0, D3D11_CREATE_DEVICE_BGRA_SUPPORT, feature_levels.begin(),
|
||||||
|
static_cast<UINT>(feature_levels.size()), D3D11_SDK_VERSION,
|
||||||
|
&_D3D11Device, 0, &_D3D11DeviceContext);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
std::cout << "Failed to create D3D device" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device = nullptr;
|
||||||
|
auto dxgi_device_success = _D3D11Device->QueryInterface(
|
||||||
|
__uuidof(IDXGIDevice), (void **)&dxgi_device);
|
||||||
|
if (SUCCEEDED(dxgi_device_success) && dxgi_device != nullptr) {
|
||||||
|
dxgi_device->SetGPUThreadPriority(5); // Must be in interval [-7, 7].
|
||||||
|
}
|
||||||
|
|
||||||
|
if(IsNTHandleSupported(_D3D11Device)) {
|
||||||
|
std::cout << "NT HANDLE SUPPORT" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "NT HANDLE NOT SUPPORT" << std::endl;
|
||||||
|
}
|
||||||
|
auto level = _D3D11Device->GetFeatureLevel();
|
||||||
|
std::cout << "Direct3D Feature Level: "
|
||||||
|
<< (((unsigned)level) >> 12) << "_"
|
||||||
|
<< ((((unsigned)level) >> 8) & 0xf) << std::endl;
|
||||||
|
|
||||||
|
// Create texture
|
||||||
|
auto d3d11_texture2D_desc = D3D11_TEXTURE2D_DESC{0};
|
||||||
|
d3d11_texture2D_desc.Width = width;
|
||||||
|
d3d11_texture2D_desc.Height = height;
|
||||||
|
d3d11_texture2D_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
d3d11_texture2D_desc.MipLevels = 1;
|
||||||
|
d3d11_texture2D_desc.ArraySize = 1;
|
||||||
|
d3d11_texture2D_desc.SampleDesc.Count = 1;
|
||||||
|
d3d11_texture2D_desc.SampleDesc.Quality = 0;
|
||||||
|
d3d11_texture2D_desc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
d3d11_texture2D_desc.BindFlags =
|
||||||
|
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||||
|
d3d11_texture2D_desc.CPUAccessFlags = 0;
|
||||||
|
d3d11_texture2D_desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
||||||
|
|
||||||
|
hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr, &_d3dTexture2D);
|
||||||
|
if FAILED (hr) {
|
||||||
|
std::cout << "Failed to create D3D texture (" << hr << ")" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto resource = Microsoft::WRL::ComPtr<IDXGIResource1>{};
|
||||||
|
hr = _d3dTexture2D.As(&resource);
|
||||||
|
|
||||||
|
if FAILED (hr) {
|
||||||
|
std::cout << "Failed to create D3D texture" << std::endl;
|
||||||
|
return;
|
||||||
|
;
|
||||||
|
}
|
||||||
|
hr = resource->GetSharedHandle(&_d3dTexture2DHandle);
|
||||||
|
if FAILED (hr) {
|
||||||
|
std::cout << "Failed to get shared handle to external D3D texture" << std::endl;
|
||||||
|
return;
|
||||||
|
;
|
||||||
|
}
|
||||||
|
_d3dTexture2D->AddRef();
|
||||||
|
|
||||||
|
std::cout << "Created external D3D texture " << width << "x" << height << std::endl;
|
||||||
|
|
||||||
|
// Create render target view of the texture
|
||||||
|
ID3D11RenderTargetView* rtv = nullptr;
|
||||||
|
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
|
||||||
|
rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||||
|
rtvDesc.Texture2D.MipSlice = 0;
|
||||||
|
|
||||||
|
hr = _D3D11Device->CreateRenderTargetView(_d3dTexture2D.Get(), &rtvDesc, &rtv);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
std::cout << "Failed to create render target view" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the texture to blue
|
||||||
|
float blueColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; // RGBA
|
||||||
|
_D3D11DeviceContext->ClearRenderTargetView(rtv, blueColor);
|
||||||
|
_D3D11DeviceContext->Flush();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3DTexture::FillBlueAndSaveToBMP(const char* filename) {
|
||||||
|
// Create render target view of the texture
|
||||||
|
ID3D11RenderTargetView* rtv = nullptr;
|
||||||
|
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
|
||||||
|
rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||||
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||||
|
rtvDesc.Texture2D.MipSlice = 0;
|
||||||
|
|
||||||
|
HRESULT hr = _D3D11Device->CreateRenderTargetView(_d3dTexture2D.Get(), &rtvDesc, &rtv);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
std::cout << "Failed to create render target view" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the texture to blue
|
||||||
|
float blueColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; // RGBA
|
||||||
|
_D3D11DeviceContext->ClearRenderTargetView(rtv, blueColor);
|
||||||
|
|
||||||
|
// Create staging texture for CPU read access
|
||||||
|
D3D11_TEXTURE2D_DESC stagingDesc = {};
|
||||||
|
_d3dTexture2D->GetDesc(&stagingDesc);
|
||||||
|
stagingDesc.Usage = D3D11_USAGE_STAGING;
|
||||||
|
stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||||
|
stagingDesc.BindFlags = 0;
|
||||||
|
stagingDesc.MiscFlags = 0;
|
||||||
|
|
||||||
|
ID3D11Texture2D* stagingTexture = nullptr;
|
||||||
|
hr = _D3D11Device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
rtv->Release();
|
||||||
|
std::cout << "Failed to create staging texture" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy to staging texture
|
||||||
|
_D3D11DeviceContext->CopyResource(stagingTexture, _d3dTexture2D.Get());
|
||||||
|
|
||||||
|
// Save to BMP
|
||||||
|
bool success = SaveTextureAsBMP(stagingTexture, filename);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
stagingTexture->Release();
|
||||||
|
rtv->Release();
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
std::cout << "Successfully saved texture to " << filename << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool D3DTexture::SaveTextureAsBMP(ID3D11Texture2D* texture, const char* filename) {
|
||||||
|
D3D11_TEXTURE2D_DESC desc;
|
||||||
|
texture->GetDesc(&desc);
|
||||||
|
|
||||||
|
// Map texture to get pixel data
|
||||||
|
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||||
|
HRESULT hr = _D3D11DeviceContext->Map(texture, 0, D3D11_MAP_READ, 0, &mappedResource);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
std::cout << "Failed to map texture" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BMP file header
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct BMPHeader {
|
||||||
|
uint16_t signature;
|
||||||
|
uint32_t fileSize;
|
||||||
|
uint32_t reserved;
|
||||||
|
uint32_t dataOffset;
|
||||||
|
uint32_t headerSize;
|
||||||
|
int32_t width;
|
||||||
|
int32_t height;
|
||||||
|
uint16_t planes;
|
||||||
|
uint16_t bitsPerPixel;
|
||||||
|
uint32_t compression;
|
||||||
|
uint32_t imageSize;
|
||||||
|
int32_t xPixelsPerMeter;
|
||||||
|
int32_t yPixelsPerMeter;
|
||||||
|
uint32_t totalColors;
|
||||||
|
uint32_t importantColors;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
// Create and fill header
|
||||||
|
BMPHeader header = {};
|
||||||
|
header.signature = 0x4D42; // 'BM'
|
||||||
|
header.fileSize = sizeof(BMPHeader) + desc.Width * desc.Height * 4;
|
||||||
|
header.dataOffset = sizeof(BMPHeader);
|
||||||
|
header.headerSize = 40;
|
||||||
|
header.width = desc.Width;
|
||||||
|
header.height = desc.Height;
|
||||||
|
header.planes = 1;
|
||||||
|
header.bitsPerPixel = 32;
|
||||||
|
header.compression = 0;
|
||||||
|
header.imageSize = desc.Width * desc.Height * 4;
|
||||||
|
header.xPixelsPerMeter = 2835; // 72 DPI
|
||||||
|
header.yPixelsPerMeter = 2835; // 72 DPI
|
||||||
|
|
||||||
|
// Write to file
|
||||||
|
FILE* file = nullptr;
|
||||||
|
fopen_s(&file, filename, "wb");
|
||||||
|
if (!file) {
|
||||||
|
_D3D11DeviceContext->Unmap(texture, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(&header, sizeof(header), 1, file);
|
||||||
|
|
||||||
|
// Write pixel data (need to flip rows as BMP is bottom-up)
|
||||||
|
uint8_t* srcData = reinterpret_cast<uint8_t*>(mappedResource.pData);
|
||||||
|
for (int y = desc.Height - 1; y >= 0; y--) {
|
||||||
|
uint8_t* rowData = srcData + y * mappedResource.RowPitch;
|
||||||
|
fwrite(rowData, desc.Width * 4, 1, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
_D3D11DeviceContext->Unmap(texture, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace thermion_flutter
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include <d3d.h>
|
||||||
|
#include <d3d11.h>
|
||||||
|
#include <dxgi1_2.h> // Add this line
|
||||||
|
#include <d3d11_4.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <wrl.h>
|
||||||
|
|
||||||
|
typedef uint32_t GLuint;
|
||||||
|
|
||||||
|
namespace thermion::windows::d3d {
|
||||||
|
|
||||||
|
class D3DTexture {
|
||||||
|
public:
|
||||||
|
D3DTexture(
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
std::function<void(size_t, size_t)> onResizeRequested
|
||||||
|
);
|
||||||
|
~D3DTexture();
|
||||||
|
|
||||||
|
void Flush();
|
||||||
|
HANDLE GetTextureHandle();
|
||||||
|
|
||||||
|
GLuint glTextureId = 0;
|
||||||
|
|
||||||
|
void FillBlueAndSaveToBMP(const char* filename);
|
||||||
|
bool SaveTextureAsBMP(ID3D11Texture2D* texture, const char* filename);
|
||||||
|
// Device
|
||||||
|
ID3D11Device* _D3D11Device = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _error = false;
|
||||||
|
uint32_t _width = 0;
|
||||||
|
uint32_t _height = 0;
|
||||||
|
bool logged = false;
|
||||||
|
std::function<void(size_t, size_t)> _onResizeRequested;
|
||||||
|
|
||||||
|
|
||||||
|
ID3D11DeviceContext* _D3D11DeviceContext = nullptr;
|
||||||
|
// Texture objects/shared handles
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11Texture2D> _d3dTexture2D;
|
||||||
|
HANDLE _d3dTexture2DHandle = nullptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "egl_texture.h"
|
||||||
|
|
||||||
|
namespace thermion::windows::egl {
|
||||||
|
|
||||||
|
class ThermionEGLContext {
|
||||||
|
public:
|
||||||
|
ThermionEGLContext();
|
||||||
|
void* GetSharedContext();
|
||||||
|
EGLTexture * CreateRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top);
|
||||||
|
void DestroyRenderingSurface();
|
||||||
|
void ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top);
|
||||||
|
|
||||||
|
EGLTexture * GetActiveTexture();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* _context = nullptr;
|
||||||
|
EGLConfig _eglConfig = NULL;
|
||||||
|
EGLDisplay _eglDisplay = NULL;
|
||||||
|
ID3D11Device* _D3D11Device = nullptr;
|
||||||
|
ID3D11DeviceContext* _D3D11DeviceContext = nullptr;
|
||||||
|
std::unique_ptr<EGLTexture> _active = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,484 @@
|
|||||||
|
#include "d3d_texture.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <vulkan/vulkan_win32.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "d3d_texture.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
// Helper function to convert VkResult to string for error reporting
|
||||||
|
const char *VkResultToString(VkResult result)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case VK_SUCCESS:
|
||||||
|
return "VK_SUCCESS";
|
||||||
|
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||||
|
return "VK_ERROR_OUT_OF_HOST_MEMORY";
|
||||||
|
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||||
|
return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
|
||||||
|
case VK_ERROR_INITIALIZATION_FAILED:
|
||||||
|
return "VK_ERROR_INITIALIZATION_FAILED";
|
||||||
|
case VK_ERROR_LAYER_NOT_PRESENT:
|
||||||
|
return "VK_ERROR_LAYER_NOT_PRESENT";
|
||||||
|
case VK_ERROR_EXTENSION_NOT_PRESENT:
|
||||||
|
return "VK_ERROR_EXTENSION_NOT_PRESENT";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN_ERROR";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modified memory type selection function with more detailed requirements checking
|
||||||
|
uint32_t findOptimalMemoryType(VkPhysicalDevice physicalDevice,
|
||||||
|
uint32_t typeFilter,
|
||||||
|
VkMemoryPropertyFlags requiredProperties,
|
||||||
|
VkMemoryPropertyFlags preferredProperties = 0) {
|
||||||
|
VkPhysicalDeviceMemoryProperties memProperties;
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
|
||||||
|
|
||||||
|
// First try to find memory type with all preferred properties
|
||||||
|
if (preferredProperties != 0) {
|
||||||
|
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
|
||||||
|
if ((typeFilter & (1 << i)) &&
|
||||||
|
(memProperties.memoryTypes[i].propertyFlags & (requiredProperties | preferredProperties)) ==
|
||||||
|
(requiredProperties | preferredProperties)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to just required properties
|
||||||
|
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
|
||||||
|
if ((typeFilter & (1 << i)) &&
|
||||||
|
(memProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consolidated function for creating Vulkan instance
|
||||||
|
VkResult createVulkanInstance(VkInstance *instance)
|
||||||
|
{
|
||||||
|
std::vector<const char *> instanceExtensions = {
|
||||||
|
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||||
|
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
|
||||||
|
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
|
||||||
|
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME};
|
||||||
|
|
||||||
|
VkApplicationInfo appInfo = {};
|
||||||
|
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
|
appInfo.pApplicationName = "Vulkan-D3D11 Interop";
|
||||||
|
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||||
|
appInfo.pEngineName = "No Engine";
|
||||||
|
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||||
|
appInfo.apiVersion = VK_API_VERSION_1_1;
|
||||||
|
|
||||||
|
VkInstanceCreateInfo createInfo = {};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
createInfo.pApplicationInfo = &appInfo;
|
||||||
|
createInfo.enabledExtensionCount = static_cast<uint32_t>(instanceExtensions.size());
|
||||||
|
createInfo.ppEnabledExtensionNames = instanceExtensions.data();
|
||||||
|
|
||||||
|
return vkCreateInstance(&createInfo, nullptr, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consolidated function for creating logical device
|
||||||
|
VkResult createLogicalDevice(VkInstance instance, VkPhysicalDevice *physicalDevice, VkDevice *device)
|
||||||
|
{
|
||||||
|
uint32_t deviceCount = 0;
|
||||||
|
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
|
||||||
|
std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
|
||||||
|
vkEnumeratePhysicalDevices(instance, &deviceCount, physicalDevices.data());
|
||||||
|
|
||||||
|
if (deviceCount == 0)
|
||||||
|
{
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
*physicalDevice = physicalDevices[0];
|
||||||
|
|
||||||
|
std::vector<const char *> deviceExtensions = {
|
||||||
|
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
|
||||||
|
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME};
|
||||||
|
|
||||||
|
float queuePriority = 1.0f;
|
||||||
|
VkDeviceQueueCreateInfo queueCreateInfo = {};
|
||||||
|
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
|
queueCreateInfo.queueFamilyIndex = 0;
|
||||||
|
queueCreateInfo.queueCount = 1;
|
||||||
|
queueCreateInfo.pQueuePriorities = &queuePriority;
|
||||||
|
|
||||||
|
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||||
|
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
|
deviceCreateInfo.queueCreateInfoCount = 1;
|
||||||
|
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
|
||||||
|
deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
||||||
|
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
|
||||||
|
|
||||||
|
return vkCreateDevice(*physicalDevice, &deviceCreateInfo, nullptr, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkD3D11VulkanInterop(VkPhysicalDevice physicalDevice, ID3D11Device *d3dDevice)
|
||||||
|
{
|
||||||
|
std::cout << "\n=== Checking D3D11-Vulkan Interop Support in QEMU ===" << std::endl;
|
||||||
|
|
||||||
|
// Check Vulkan external memory capabilities
|
||||||
|
VkPhysicalDeviceExternalImageFormatInfo externFormatInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
|
||||||
|
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT};
|
||||||
|
|
||||||
|
VkPhysicalDeviceImageFormatInfo2 formatInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
|
||||||
|
.pNext = &externFormatInfo,
|
||||||
|
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
.type = VK_IMAGE_TYPE_2D,
|
||||||
|
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||||
|
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
|
.flags = 0};
|
||||||
|
|
||||||
|
VkExternalImageFormatProperties externFormatProps = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES};
|
||||||
|
|
||||||
|
VkImageFormatProperties2 formatProps = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
|
||||||
|
.pNext = &externFormatProps};
|
||||||
|
|
||||||
|
// Check device properties
|
||||||
|
VkPhysicalDeviceProperties deviceProps;
|
||||||
|
vkGetPhysicalDeviceProperties(physicalDevice, &deviceProps);
|
||||||
|
|
||||||
|
std::cout << "Vulkan Device: " << deviceProps.deviceName << std::endl;
|
||||||
|
std::cout << "Driver Version: " << deviceProps.driverVersion << std::endl;
|
||||||
|
std::cout << "API Version: " << VK_VERSION_MAJOR(deviceProps.apiVersion) << "." << VK_VERSION_MINOR(deviceProps.apiVersion) << "." << VK_VERSION_PATCH(deviceProps.apiVersion) << std::endl;
|
||||||
|
|
||||||
|
// Check D3D11 device capabilities
|
||||||
|
D3D11_FEATURE_DATA_D3D11_OPTIONS3 featureData = {};
|
||||||
|
HRESULT hr = d3dDevice->CheckFeatureSupport(
|
||||||
|
D3D11_FEATURE_D3D11_OPTIONS3,
|
||||||
|
&featureData,
|
||||||
|
sizeof(featureData));
|
||||||
|
|
||||||
|
std::cout << "\nChecking D3D11 Device:" << std::endl;
|
||||||
|
|
||||||
|
// Get D3D11 device information
|
||||||
|
IDXGIDevice *dxgiDevice = nullptr;
|
||||||
|
hr = d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
IDXGIAdapter *adapter = nullptr;
|
||||||
|
hr = dxgiDevice->GetAdapter(&adapter);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DXGI_ADAPTER_DESC desc;
|
||||||
|
adapter->GetDesc(&desc);
|
||||||
|
std::wcout << L"D3D11 Adapter: " << desc.Description << std::endl;
|
||||||
|
adapter->Release();
|
||||||
|
}
|
||||||
|
dxgiDevice->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for external memory support
|
||||||
|
VkResult result = vkGetPhysicalDeviceImageFormatProperties2(
|
||||||
|
physicalDevice,
|
||||||
|
&formatInfo,
|
||||||
|
&formatProps);
|
||||||
|
|
||||||
|
std::cout << "\nInterop Support Details:" << std::endl;
|
||||||
|
|
||||||
|
// Check external memory extension
|
||||||
|
uint32_t extensionCount = 0;
|
||||||
|
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr);
|
||||||
|
std::vector<VkExtensionProperties> extensions(extensionCount);
|
||||||
|
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, extensions.data());
|
||||||
|
|
||||||
|
bool hasExternalMemoryExt = false;
|
||||||
|
bool hasWin32Ext = false;
|
||||||
|
|
||||||
|
for (const auto &ext : extensions)
|
||||||
|
{
|
||||||
|
if (strcmp(ext.extensionName, VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME) == 0)
|
||||||
|
{
|
||||||
|
hasExternalMemoryExt = true;
|
||||||
|
}
|
||||||
|
if (strcmp(ext.extensionName, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME) == 0)
|
||||||
|
{
|
||||||
|
hasWin32Ext = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "External Memory Extension: " << (hasExternalMemoryExt ? "Yes" : "No") << std::endl;
|
||||||
|
std::cout << "Win32 External Memory Extension: " << (hasWin32Ext ? "Yes" : "No") << std::endl;
|
||||||
|
std::cout << "Format Properties Check: " << (result == VK_SUCCESS ? "Passed" : "Failed") << std::endl;
|
||||||
|
|
||||||
|
// Check memory properties
|
||||||
|
VkPhysicalDeviceMemoryProperties memProps;
|
||||||
|
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps);
|
||||||
|
|
||||||
|
std::cout << "\nMemory Types Available:" << std::endl;
|
||||||
|
for (uint32_t i = 0; i < memProps.memoryTypeCount; i++)
|
||||||
|
{
|
||||||
|
VkMemoryPropertyFlags flags = memProps.memoryTypes[i].propertyFlags;
|
||||||
|
std::cout << "Type " << i << ": ";
|
||||||
|
if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||||
|
std::cout << "Device Local ";
|
||||||
|
if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||||
|
std::cout << "Host Visible ";
|
||||||
|
if (flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
||||||
|
std::cout << "Host Coherent ";
|
||||||
|
if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
|
||||||
|
std::cout << "Host Cached ";
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if all required features are available
|
||||||
|
bool supportsInterop =
|
||||||
|
hasExternalMemoryExt &&
|
||||||
|
hasWin32Ext &&
|
||||||
|
result == VK_SUCCESS;
|
||||||
|
|
||||||
|
std::cout << "\nFinal Result: " << (supportsInterop ? "Interop Supported" : "Interop Not Supported") << std::endl;
|
||||||
|
std::cout << "================================================" << std::endl;
|
||||||
|
|
||||||
|
return supportsInterop;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
VkInstance instance = VK_NULL_HANDLE;
|
||||||
|
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||||
|
VkDevice device = VK_NULL_HANDLE;
|
||||||
|
VkImage image = VK_NULL_HANDLE;
|
||||||
|
HANDLE sharedHandle = nullptr;
|
||||||
|
|
||||||
|
uint32_t height = 100;
|
||||||
|
uint32_t width = 100;
|
||||||
|
|
||||||
|
std::cout << "[Step 1] Initializing D3D texture..." << std::endl;
|
||||||
|
thermion::windows::d3d::D3DTexture texture(width, height, [=](size_t width, size_t height) {});
|
||||||
|
|
||||||
|
sharedHandle = texture.GetTextureHandle();
|
||||||
|
if (!sharedHandle)
|
||||||
|
{
|
||||||
|
std::cout << "[ERROR] Failed to get shared texture handle!" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture.FillBlueAndSaveToBMP("output.bmp");
|
||||||
|
std::cout << "[Info] Filled texture with blue and saved to output.bmp" << std::endl;
|
||||||
|
|
||||||
|
// Create Vulkan instance
|
||||||
|
VkResult result = createVulkanInstance(&instance);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
std::cout << "[ERROR] Failed to create Vulkan instance! Error: " << VkResultToString(result) << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create logical device
|
||||||
|
result = createLogicalDevice(instance, &physicalDevice, &device);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
std::cout << "[ERROR] Failed to create logical device! Error: " << VkResultToString(result) << std::endl;
|
||||||
|
vkDestroyInstance(instance, nullptr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In main(), after creating both D3D11 and Vulkan devices:
|
||||||
|
texture.FillBlueAndSaveToBMP("output.bmp");
|
||||||
|
if (!checkD3D11VulkanInterop(physicalDevice, texture._D3D11Device))
|
||||||
|
{
|
||||||
|
std::cout << "D3D11-Vulkan interop is not supported in this QEMU environment" << std::endl;
|
||||||
|
// Consider falling back to a different approach
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPhysicalDeviceExternalImageFormatInfo externFormatInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT};
|
||||||
|
|
||||||
|
VkPhysicalDeviceImageFormatInfo2 formatInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
|
||||||
|
.pNext = &externFormatInfo,
|
||||||
|
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
.type = VK_IMAGE_TYPE_2D,
|
||||||
|
.tiling = VK_IMAGE_TILING_OPTIMAL, // Changed to LINEAR for VM compatibility
|
||||||
|
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // Simplified usage flags
|
||||||
|
.flags = 0};
|
||||||
|
|
||||||
|
VkExternalImageFormatProperties externFormatProps = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES};
|
||||||
|
|
||||||
|
VkImageFormatProperties2 formatProps = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
|
||||||
|
.pNext = &externFormatProps};
|
||||||
|
|
||||||
|
// Query supported features
|
||||||
|
result = vkGetPhysicalDeviceImageFormatProperties2(
|
||||||
|
physicalDevice,
|
||||||
|
&formatInfo,
|
||||||
|
&formatProps);
|
||||||
|
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
std::cout << "VM environment may not support required external memory features" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "VM environment supports required external memory features" << std::endl;
|
||||||
|
|
||||||
|
// Create image with external memory support
|
||||||
|
VkExternalMemoryImageCreateInfo extImageInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||||
|
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT};
|
||||||
|
|
||||||
|
VkImageCreateInfo imageInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||||
|
.pNext = &extImageInfo,
|
||||||
|
.flags = 0,
|
||||||
|
.imageType = VK_IMAGE_TYPE_2D,
|
||||||
|
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
.extent = {width, height, 1},
|
||||||
|
.mipLevels = 1,
|
||||||
|
.arrayLayers = 1,
|
||||||
|
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
.tiling = VK_IMAGE_TILING_OPTIMAL, // Changed to LINEAR for VM
|
||||||
|
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // Simplified usage
|
||||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED};
|
||||||
|
|
||||||
|
result = vkCreateImage(device, &imageInfo, nullptr, &image);
|
||||||
|
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to create iamge " << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Successfully created image " << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkMemoryDedicatedRequirements MemoryDedicatedRequirements{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
|
||||||
|
.pNext = nullptr};
|
||||||
|
VkMemoryRequirements2 MemoryRequirements2{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||||
|
.pNext = &MemoryDedicatedRequirements};
|
||||||
|
const VkImageMemoryRequirementsInfo2 ImageMemoryRequirementsInfo2{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.image = image};
|
||||||
|
// WARN: Memory access violation unless validation instance layer is enabled, otherwise success but...
|
||||||
|
vkGetImageMemoryRequirements2(device, &ImageMemoryRequirementsInfo2, &MemoryRequirements2);
|
||||||
|
// ... if we happen to be here, MemoryRequirements2 is empty
|
||||||
|
VkMemoryRequirements &MemoryRequirements = MemoryRequirements2.memoryRequirements;
|
||||||
|
|
||||||
|
const VkMemoryDedicatedAllocateInfo MemoryDedicatedAllocateInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.image = image,
|
||||||
|
.buffer = VK_NULL_HANDLE};
|
||||||
|
const VkImportMemoryWin32HandleInfoKHR ImportMemoryWin32HandleInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
|
||||||
|
.pNext = &MemoryDedicatedAllocateInfo,
|
||||||
|
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
|
||||||
|
.handle = sharedHandle,
|
||||||
|
.name = nullptr};
|
||||||
|
VkDeviceMemory ImageMemory = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
// Find suitable memory type
|
||||||
|
uint32_t memoryTypeIndex = findOptimalMemoryType(
|
||||||
|
physicalDevice,
|
||||||
|
MemoryRequirements.memoryTypeBits,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT // You might need to adjust these flags
|
||||||
|
);
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo allocInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
|
.pNext = &ImportMemoryWin32HandleInfo,
|
||||||
|
.allocationSize = MemoryRequirements.size,
|
||||||
|
.memoryTypeIndex = memoryTypeIndex // Assuming 'properties' is your memory type index
|
||||||
|
};
|
||||||
|
|
||||||
|
VkResult allocResult = vkAllocateMemory(device, &allocInfo, nullptr, &ImageMemory);
|
||||||
|
if (allocResult != VK_SUCCESS || ImageMemory == VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
std::cout << "IMAGE MEMORY ALLOCATION FAILED:" << std::endl;
|
||||||
|
std::cout << " Allocation size: " << MemoryRequirements.size << " bytes" << std::endl;
|
||||||
|
std::cout << " Memory type index: " << allocInfo.memoryTypeIndex << std::endl;
|
||||||
|
std::cout << " Error code: " << allocResult << std::endl;
|
||||||
|
|
||||||
|
// Get more detailed error message based on VkResult
|
||||||
|
const char *errorMsg;
|
||||||
|
switch (allocResult)
|
||||||
|
{
|
||||||
|
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||||
|
errorMsg = "VK_ERROR_OUT_OF_HOST_MEMORY: Out of host memory";
|
||||||
|
break;
|
||||||
|
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||||
|
errorMsg = "VK_ERROR_OUT_OF_DEVICE_MEMORY: Out of device memory";
|
||||||
|
break;
|
||||||
|
case VK_ERROR_INVALID_EXTERNAL_HANDLE:
|
||||||
|
errorMsg = "VK_ERROR_INVALID_EXTERNAL_HANDLE: The external handle is invalid";
|
||||||
|
break;
|
||||||
|
case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS:
|
||||||
|
errorMsg = "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: The requested address is not available";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorMsg = "Unknown error";
|
||||||
|
}
|
||||||
|
std::cout << " Error message: " << errorMsg << std::endl;
|
||||||
|
|
||||||
|
// Print shared handle info
|
||||||
|
std::cout << " Shared handle value: " << sharedHandle << std::endl;
|
||||||
|
|
||||||
|
// Print memory requirements
|
||||||
|
std::cout << " Memory requirements:" << std::endl;
|
||||||
|
std::cout << " Size: " << MemoryRequirements.size << std::endl;
|
||||||
|
std::cout << " Alignment: " << MemoryRequirements.alignment << std::endl;
|
||||||
|
std::cout << " Memory type bits: 0x" << std::hex << MemoryRequirements.memoryTypeBits << std::dec << std::endl;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// memAllocator->Allocate(MemoryRequirements, &ImageMemory, properties, &ImportMemoryWin32HandleInfo);
|
||||||
|
// if(ImageMemory == VK_NULL_HANDLE) {
|
||||||
|
// std::cout << "IMAGE MEMORY ALLOCATION FAILED" << std::endl;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
const VkBindImageMemoryInfo bindImageMemoryInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.image = image,
|
||||||
|
.memory = ImageMemory,
|
||||||
|
.memoryOffset = 0};
|
||||||
|
|
||||||
|
result = vkBindImageMemory2(device, 1, &bindImageMemoryInfo);
|
||||||
|
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
std::cout << "bindimagememory2 failed" << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << "FIISHED" << std::endl;
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
std::cout << "\n[Step 6] Cleaning up resources..." << std::endl;
|
||||||
|
vkDestroyImage(device, image, nullptr);
|
||||||
|
// vkFreeMemory(device, memory, nullptr);
|
||||||
|
vkDestroyDevice(device, nullptr);
|
||||||
|
vkDestroyInstance(instance, nullptr);
|
||||||
|
std::cout << "[Complete] All resources cleaned up successfully" << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "egl_context.h"
|
||||||
|
|
||||||
|
namespace thermion::windows::vulkan {
|
||||||
|
|
||||||
|
ThermionEGLContext::ThermionEGLContext() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// *******************
|
||||||
|
// * *
|
||||||
|
// * *
|
||||||
|
// * EGL starts here *
|
||||||
|
// * *
|
||||||
|
// * *
|
||||||
|
// * *
|
||||||
|
// *******************
|
||||||
|
EGLBoolean bindAPI = eglBindAPI(EGL_OPENGL_ES_API);
|
||||||
|
if (!bindAPI) {
|
||||||
|
std::cout << "eglBindAPI EGL_OPENGL_ES_API failed" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
|
if (_eglDisplay == EGL_NO_DISPLAY) {
|
||||||
|
std::cout << "eglBindAPI EGL_OPENGL_ES_API failed" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EGLint major, minor;
|
||||||
|
EGLBoolean initialized = false;
|
||||||
|
|
||||||
|
EGLDeviceEXT eglDevice;
|
||||||
|
EGLint numDevices;
|
||||||
|
|
||||||
|
if (auto *getPlatformDisplay =
|
||||||
|
reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
|
||||||
|
eglGetProcAddress("eglGetPlatformDisplayEXT"))) {
|
||||||
|
|
||||||
|
EGLint kD3D11DisplayAttributes[] = {
|
||||||
|
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
|
||||||
|
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
|
||||||
|
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
|
||||||
|
EGL_TRUE,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
_eglDisplay = getPlatformDisplay(
|
||||||
|
EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, kD3D11DisplayAttributes);
|
||||||
|
initialized = eglInitialize(_eglDisplay, &major, &minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Got major " << major << " and minor " << minor << std::endl;
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
std::cout << "eglInitialize failed" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// glext::importGLESExtensionsEntryPoints();
|
||||||
|
|
||||||
|
EGLint configsCount;
|
||||||
|
|
||||||
|
EGLint configAttribs[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
|
||||||
|
EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 24,
|
||||||
|
EGL_STENCIL_SIZE, 8, EGL_ALPHA_SIZE, 8,
|
||||||
|
EGL_NONE};
|
||||||
|
|
||||||
|
EGLint contextAttribs[] = {
|
||||||
|
EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE,
|
||||||
|
EGL_NONE, // reserved for EGL_CONTEXT_OPENGL_NO_ERROR_KHR below
|
||||||
|
EGL_NONE};
|
||||||
|
|
||||||
|
// find an opaque config
|
||||||
|
if (!eglChooseConfig(_eglDisplay, configAttribs, &_eglConfig, 1,
|
||||||
|
&configsCount)) {
|
||||||
|
std::cout << "Failed to find EGL config" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ctx = eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT,contextAttribs);
|
||||||
|
_context = (void*)ctx;
|
||||||
|
|
||||||
|
if (_context == EGL_NO_CONTEXT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLTexture* ThermionEGLContext::CreateRenderingSurface(
|
||||||
|
uint32_t width, uint32_t height,
|
||||||
|
uint32_t left, uint32_t top
|
||||||
|
) {
|
||||||
|
|
||||||
|
// glext::importGLESExtensionsEntryPoints();
|
||||||
|
|
||||||
|
if(left != 0 || top != 0) {
|
||||||
|
std::cout << "ERROR Rendering with EGL uses a Texture render target/Flutter widget and does not need a window offset." << std::endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (_active && _active.get()) {
|
||||||
|
// // result->Error("ERROR",
|
||||||
|
// // "Texture already exists. You must call destroyTexture before "
|
||||||
|
// // "attempting to create a new one.");
|
||||||
|
// return nullptr;
|
||||||
|
//}
|
||||||
|
|
||||||
|
_active = std::make_unique<EGLTexture>(
|
||||||
|
width, height,
|
||||||
|
_D3D11Device, _D3D11DeviceContext, _eglConfig, _eglDisplay, _context,
|
||||||
|
[=](size_t width, size_t height) {
|
||||||
|
std::cout << "RESIZE" << std::endl;
|
||||||
|
std::vector<int64_t> list;
|
||||||
|
list.push_back((int64_t)width);
|
||||||
|
list.push_back((int64_t)height);
|
||||||
|
// auto val = std::make_unique<flutter::EncodableValue>(list);
|
||||||
|
// this->_channel->InvokeMethod("resize", std::move(val), nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
return _active.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ThermionEGLContext::GetSharedContext() {
|
||||||
|
return (void*)_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThermionEGLContext::ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThermionEGLContext::DestroyRenderingSurface() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLTexture *ThermionEGLContext::GetActiveTexture() {
|
||||||
|
return _active.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user