mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
Vulkan: Fix compilation on 32-bit targets
This commit is contained in:
parent
d139659ea2
commit
1286c309e3
@ -40,7 +40,7 @@ private:
|
||||
void Readback(StateTracker* state_tracker);
|
||||
|
||||
VkBuffer m_gpu_buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory m_gpu_memory = nullptr;
|
||||
VkDeviceMemory m_gpu_memory = VK_NULL_HANDLE;
|
||||
|
||||
static const size_t NUM_VALUES = 4;
|
||||
static const size_t BUFFER_SIZE = sizeof(u32) * NUM_VALUES;
|
||||
|
@ -73,7 +73,7 @@ void CommandBufferManager::DestroyCommandPool()
|
||||
if (m_command_pool)
|
||||
{
|
||||
vkDestroyCommandPool(g_vulkan_context->GetDevice(), m_command_pool, nullptr);
|
||||
m_command_pool = nullptr;
|
||||
m_command_pool = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,8 +141,8 @@ void CommandBufferManager::DestroyCommandBuffers()
|
||||
|
||||
for (FrameResources& resources : m_frame_resources)
|
||||
{
|
||||
for (const auto& it : resources.cleanup_resources)
|
||||
it.destroy_callback(device, it.object);
|
||||
for (auto& it : resources.cleanup_resources)
|
||||
it();
|
||||
resources.cleanup_resources.clear();
|
||||
|
||||
if (resources.fence != VK_NULL_HANDLE)
|
||||
@ -385,8 +385,8 @@ void CommandBufferManager::OnCommandBufferExecuted(size_t index)
|
||||
iter.second.second(resources.fence);
|
||||
|
||||
// Clean up all objects pending destruction on this command buffer
|
||||
for (const auto& it : resources.cleanup_resources)
|
||||
it.destroy_callback(g_vulkan_context->GetDevice(), it.object);
|
||||
for (auto& it : resources.cleanup_resources)
|
||||
it();
|
||||
resources.cleanup_resources.clear();
|
||||
}
|
||||
|
||||
@ -446,6 +446,48 @@ void CommandBufferManager::ExecuteCommandBuffer(bool submit_off_thread, bool wai
|
||||
WaitForFence(pending_fence);
|
||||
}
|
||||
|
||||
void CommandBufferManager::DeferBufferDestruction(VkBuffer object)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[m_current_frame];
|
||||
resources.cleanup_resources.push_back(
|
||||
[object]() { vkDestroyBuffer(g_vulkan_context->GetDevice(), object, nullptr); });
|
||||
}
|
||||
|
||||
void CommandBufferManager::DeferBufferViewDestruction(VkBufferView object)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[m_current_frame];
|
||||
resources.cleanup_resources.push_back(
|
||||
[object]() { vkDestroyBufferView(g_vulkan_context->GetDevice(), object, nullptr); });
|
||||
}
|
||||
|
||||
void CommandBufferManager::DeferDeviceMemoryDestruction(VkDeviceMemory object)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[m_current_frame];
|
||||
resources.cleanup_resources.push_back(
|
||||
[object]() { vkFreeMemory(g_vulkan_context->GetDevice(), object, nullptr); });
|
||||
}
|
||||
|
||||
void CommandBufferManager::DeferFramebufferDestruction(VkFramebuffer object)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[m_current_frame];
|
||||
resources.cleanup_resources.push_back(
|
||||
[object]() { vkDestroyFramebuffer(g_vulkan_context->GetDevice(), object, nullptr); });
|
||||
}
|
||||
|
||||
void CommandBufferManager::DeferImageDestruction(VkImage object)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[m_current_frame];
|
||||
resources.cleanup_resources.push_back(
|
||||
[object]() { vkDestroyImage(g_vulkan_context->GetDevice(), object, nullptr); });
|
||||
}
|
||||
|
||||
void CommandBufferManager::DeferImageViewDestruction(VkImageView object)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[m_current_frame];
|
||||
resources.cleanup_resources.push_back(
|
||||
[object]() { vkDestroyImageView(g_vulkan_context->GetDevice(), object, nullptr); });
|
||||
}
|
||||
|
||||
void CommandBufferManager::AddFencePointCallback(
|
||||
const void* key, const CommandBufferQueuedCallback& queued_callback,
|
||||
const CommandBufferExecutedCallback& executed_callback)
|
||||
|
@ -81,12 +81,12 @@ public:
|
||||
|
||||
// Schedule a vulkan resource for destruction later on. This will occur when the command buffer
|
||||
// is next re-used, and the GPU has finished working with the specified resource.
|
||||
template <typename T>
|
||||
void DeferResourceDestruction(T object)
|
||||
{
|
||||
DeferredResourceDestruction wrapper = DeferredResourceDestruction::Wrapper<T>(object);
|
||||
m_frame_resources[m_current_frame].cleanup_resources.push_back(wrapper);
|
||||
}
|
||||
void DeferBufferDestruction(VkBuffer object);
|
||||
void DeferBufferViewDestruction(VkBufferView object);
|
||||
void DeferDeviceMemoryDestruction(VkDeviceMemory object);
|
||||
void DeferFramebufferDestruction(VkFramebuffer object);
|
||||
void DeferImageDestruction(VkImage object);
|
||||
void DeferImageViewDestruction(VkImageView object);
|
||||
|
||||
// Instruct the manager to fire the specified callback when a fence is flagged to be signaled.
|
||||
// This happens when command buffers are executed, and can be tested if signaled, which means
|
||||
@ -124,7 +124,7 @@ private:
|
||||
bool init_command_buffer_used;
|
||||
bool needs_fence_wait;
|
||||
|
||||
std::vector<DeferredResourceDestruction> cleanup_resources;
|
||||
std::vector<std::function<void()>> cleanup_resources;
|
||||
};
|
||||
|
||||
std::array<FrameResources, NUM_COMMAND_BUFFERS> m_frame_resources = {};
|
||||
|
@ -170,9 +170,9 @@ RasterFont::RasterFont()
|
||||
RasterFont::~RasterFont()
|
||||
{
|
||||
if (m_vertex_shader != VK_NULL_HANDLE)
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_vertex_shader);
|
||||
vkDestroyShaderModule(g_vulkan_context->GetDevice(), m_vertex_shader, nullptr);
|
||||
if (m_fragment_shader != VK_NULL_HANDLE)
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_fragment_shader);
|
||||
vkDestroyShaderModule(g_vulkan_context->GetDevice(), m_fragment_shader, nullptr);
|
||||
}
|
||||
|
||||
bool RasterFont::Initialize()
|
||||
@ -279,8 +279,8 @@ bool RasterFont::CreateTexture()
|
||||
// Free temp buffers after command buffer executes
|
||||
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
g_command_buffer_mgr->DeferResourceDestruction(temp_buffer);
|
||||
g_command_buffer_mgr->DeferResourceDestruction(temp_buffer_memory);
|
||||
g_command_buffer_mgr->DeferBufferDestruction(temp_buffer);
|
||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(temp_buffer_memory);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -164,13 +164,13 @@ void Renderer::DestroySemaphores()
|
||||
if (m_image_available_semaphore)
|
||||
{
|
||||
vkDestroySemaphore(g_vulkan_context->GetDevice(), m_image_available_semaphore, nullptr);
|
||||
m_image_available_semaphore = nullptr;
|
||||
m_image_available_semaphore = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
if (m_rendering_finished_semaphore)
|
||||
{
|
||||
vkDestroySemaphore(g_vulkan_context->GetDevice(), m_rendering_finished_semaphore, nullptr);
|
||||
m_rendering_finished_semaphore = nullptr;
|
||||
m_rendering_finished_semaphore = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,8 @@ private:
|
||||
|
||||
FramebufferManager* m_framebuffer_mgr = nullptr;
|
||||
|
||||
VkSemaphore m_image_available_semaphore = nullptr;
|
||||
VkSemaphore m_rendering_finished_semaphore = nullptr;
|
||||
VkSemaphore m_image_available_semaphore = VK_NULL_HANDLE;
|
||||
VkSemaphore m_rendering_finished_semaphore = VK_NULL_HANDLE;
|
||||
|
||||
std::unique_ptr<SwapChain> m_swap_chain;
|
||||
std::unique_ptr<StateTracker> m_state_tracker;
|
||||
|
@ -26,8 +26,8 @@ StagingBuffer::~StagingBuffer()
|
||||
if (m_map_pointer)
|
||||
Unmap();
|
||||
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_memory);
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_buffer);
|
||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory);
|
||||
g_command_buffer_mgr->DeferBufferDestruction(m_buffer);
|
||||
}
|
||||
|
||||
bool StagingBuffer::Map(VkDeviceSize offset, VkDeviceSize size)
|
||||
|
@ -133,8 +133,8 @@ StagingTexture2DLinear::~StagingTexture2DLinear()
|
||||
if (m_map_pointer)
|
||||
Unmap();
|
||||
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_memory);
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_image);
|
||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory);
|
||||
g_command_buffer_mgr->DeferImageDestruction(m_image);
|
||||
}
|
||||
|
||||
void StagingTexture2DLinear::CopyFromImage(VkCommandBuffer command_buffer, VkImage image,
|
||||
@ -362,8 +362,8 @@ StagingTexture2DBuffer::~StagingTexture2DBuffer()
|
||||
if (m_map_pointer)
|
||||
Unmap();
|
||||
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_memory);
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_buffer);
|
||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory);
|
||||
g_command_buffer_mgr->DeferBufferDestruction(m_buffer);
|
||||
}
|
||||
|
||||
void StagingTexture2DBuffer::CopyFromImage(VkCommandBuffer command_buffer, VkImage image,
|
||||
|
@ -539,7 +539,7 @@ void StateTracker::EndRenderPass()
|
||||
return;
|
||||
|
||||
vkCmdEndRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer());
|
||||
m_current_render_pass = nullptr;
|
||||
m_current_render_pass = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void StateTracker::BeginClearRenderPass(const VkRect2D& area, const VkClearValue clear_values[2])
|
||||
|
@ -35,9 +35,9 @@ StreamBuffer::~StreamBuffer()
|
||||
vkUnmapMemory(g_vulkan_context->GetDevice(), m_memory);
|
||||
|
||||
if (m_buffer != VK_NULL_HANDLE)
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_buffer);
|
||||
g_command_buffer_mgr->DeferBufferDestruction(m_buffer);
|
||||
if (m_memory != VK_NULL_HANDLE)
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_memory);
|
||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory);
|
||||
}
|
||||
|
||||
std::unique_ptr<StreamBuffer> StreamBuffer::Create(VkBufferUsageFlags usage, size_t initial_size,
|
||||
@ -124,9 +124,9 @@ bool StreamBuffer::ResizeBuffer(size_t size)
|
||||
|
||||
// Destroy the backings for the buffer after the command buffer executes
|
||||
if (m_buffer != VK_NULL_HANDLE)
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_buffer);
|
||||
g_command_buffer_mgr->DeferBufferDestruction(m_buffer);
|
||||
if (m_memory != VK_NULL_HANDLE)
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_memory);
|
||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_memory);
|
||||
|
||||
// Replace with the new buffer
|
||||
m_buffer = buffer;
|
||||
|
@ -280,8 +280,8 @@ void SwapChain::DestroyRenderPass()
|
||||
if (!m_render_pass)
|
||||
return;
|
||||
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_render_pass);
|
||||
m_render_pass = nullptr;
|
||||
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_render_pass, nullptr);
|
||||
m_render_pass = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
bool SwapChain::CreateSwapChain()
|
||||
|
@ -77,15 +77,15 @@ private:
|
||||
};
|
||||
|
||||
void* m_native_handle = nullptr;
|
||||
VkSurfaceKHR m_surface = nullptr;
|
||||
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
|
||||
VkSurfaceFormatKHR m_surface_format = {};
|
||||
VkPresentModeKHR m_present_mode = VK_PRESENT_MODE_RANGE_SIZE_KHR;
|
||||
|
||||
VkSwapchainKHR m_swap_chain = nullptr;
|
||||
VkSwapchainKHR m_swap_chain = VK_NULL_HANDLE;
|
||||
std::vector<SwapChainImage> m_swap_chain_images;
|
||||
u32 m_current_swap_chain_image_index = 0;
|
||||
|
||||
VkRenderPass m_render_pass = nullptr;
|
||||
VkRenderPass m_render_pass = VK_NULL_HANDLE;
|
||||
|
||||
u32 m_width = 0;
|
||||
u32 m_height = 0;
|
||||
|
@ -21,13 +21,13 @@ Texture2D::Texture2D(u32 width, u32 height, u32 levels, u32 layers, VkFormat for
|
||||
|
||||
Texture2D::~Texture2D()
|
||||
{
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_view);
|
||||
g_command_buffer_mgr->DeferImageViewDestruction(m_view);
|
||||
|
||||
// If we don't have device memory allocated, the image is not owned by us (e.g. swapchain)
|
||||
if (m_device_memory != VK_NULL_HANDLE)
|
||||
{
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_image);
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_device_memory);
|
||||
g_command_buffer_mgr->DeferImageDestruction(m_image);
|
||||
g_command_buffer_mgr->DeferDeviceMemoryDestruction(m_device_memory);
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,6 +134,8 @@ std::unique_ptr<Texture2D> Texture2D::CreateFromExistingImage(u32 width, u32 hei
|
||||
static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_COLOR_BIT),
|
||||
0, levels, 0, layers}};
|
||||
|
||||
// Memory is managed by the owner of the image.
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
VkResult res = vkCreateImageView(g_vulkan_context->GetDevice(), &view_info, nullptr, &view);
|
||||
if (res != VK_SUCCESS)
|
||||
@ -143,7 +145,7 @@ std::unique_ptr<Texture2D> Texture2D::CreateFromExistingImage(u32 width, u32 hei
|
||||
}
|
||||
|
||||
return std::make_unique<Texture2D>(width, height, levels, layers, format, samples, view_type,
|
||||
existing_image, nullptr, view);
|
||||
existing_image, memory, view);
|
||||
}
|
||||
|
||||
void Texture2D::OverrideImageLayout(VkImageLayout new_layout)
|
||||
|
@ -316,7 +316,7 @@ TextureCache::TCacheEntry::~TCacheEntry()
|
||||
m_parent->m_state_tracker->UnbindTexture(m_texture->GetView());
|
||||
|
||||
if (m_framebuffer != VK_NULL_HANDLE)
|
||||
g_command_buffer_mgr->DeferResourceDestruction(m_framebuffer);
|
||||
g_command_buffer_mgr->DeferFramebufferDestruction(m_framebuffer);
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
|
@ -260,120 +260,6 @@ VkShaderModule CompileAndCreateFragmentShader(const std::string& source_code, bo
|
||||
|
||||
} // namespace Util
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction
|
||||
DeferredResourceDestruction::Wrapper<VkCommandPool>(VkCommandPool object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.command_pool = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkDestroyCommandPool(device, obj.command_pool, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction
|
||||
DeferredResourceDestruction::Wrapper<VkDeviceMemory>(VkDeviceMemory object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.device_memory = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkFreeMemory(device, obj.device_memory, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction DeferredResourceDestruction::Wrapper<VkBuffer>(VkBuffer object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.buffer = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkDestroyBuffer(device, obj.buffer, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction DeferredResourceDestruction::Wrapper<VkBufferView>(VkBufferView object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.buffer_view = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkDestroyBufferView(device, obj.buffer_view, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction DeferredResourceDestruction::Wrapper<VkImage>(VkImage object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.image = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkDestroyImage(device, obj.image, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction DeferredResourceDestruction::Wrapper<VkImageView>(VkImageView object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.image_view = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkDestroyImageView(device, obj.image_view, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction DeferredResourceDestruction::Wrapper<VkRenderPass>(VkRenderPass object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.render_pass = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkDestroyRenderPass(device, obj.render_pass, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction
|
||||
DeferredResourceDestruction::Wrapper<VkFramebuffer>(VkFramebuffer object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.framebuffer = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkDestroyFramebuffer(device, obj.framebuffer, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction
|
||||
DeferredResourceDestruction::Wrapper<VkShaderModule>(VkShaderModule object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.shader_module = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkDestroyShaderModule(device, obj.shader_module, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DeferredResourceDestruction DeferredResourceDestruction::Wrapper<VkPipeline>(VkPipeline object)
|
||||
{
|
||||
DeferredResourceDestruction ret;
|
||||
ret.object.pipeline = object;
|
||||
ret.destroy_callback = [](VkDevice device, const Object& obj) {
|
||||
vkDestroyPipeline(device, obj.pipeline, nullptr);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
UtilityShaderDraw::UtilityShaderDraw(VkCommandBuffer command_buffer,
|
||||
VkPipelineLayout pipeline_layout, VkRenderPass render_pass,
|
||||
VkShaderModule vertex_shader, VkShaderModule geometry_shader,
|
||||
|
@ -66,28 +66,6 @@ VkShaderModule CompileAndCreateFragmentShader(const std::string& source_code,
|
||||
bool prepend_header = true);
|
||||
}
|
||||
|
||||
// Helper methods for cleaning up device objects, used by deferred destruction
|
||||
struct DeferredResourceDestruction
|
||||
{
|
||||
union Object {
|
||||
VkCommandPool command_pool;
|
||||
VkDeviceMemory device_memory;
|
||||
VkBuffer buffer;
|
||||
VkBufferView buffer_view;
|
||||
VkImage image;
|
||||
VkImageView image_view;
|
||||
VkRenderPass render_pass;
|
||||
VkFramebuffer framebuffer;
|
||||
VkShaderModule shader_module;
|
||||
VkPipeline pipeline;
|
||||
} object;
|
||||
|
||||
void (*destroy_callback)(VkDevice device, const Object& object);
|
||||
|
||||
template <typename T>
|
||||
static DeferredResourceDestruction Wrapper(T object);
|
||||
};
|
||||
|
||||
// Utility shader vertex format
|
||||
#pragma pack(push, 1)
|
||||
struct UtilityShaderVertex
|
||||
|
@ -526,7 +526,8 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
|
||||
device_info.pQueueCreateInfos = &queue_info;
|
||||
|
||||
ExtensionList enabled_extensions;
|
||||
if (!SelectDeviceExtensions(&enabled_extensions, (surface != nullptr), enable_validation_layer))
|
||||
if (!SelectDeviceExtensions(&enabled_extensions, (surface != VK_NULL_HANDLE),
|
||||
enable_validation_layer))
|
||||
return false;
|
||||
|
||||
device_info.enabledLayerCount = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user