Skip to content

Commit 5b6b58f

Browse files
committed
Implement vk::RenderTextImpl::readPixels
1 parent e450e07 commit 5b6b58f

File tree

10 files changed

+257
-103
lines changed

10 files changed

+257
-103
lines changed

axmol/rhi/vulkan/DriverVK.cpp

Lines changed: 101 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,84 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vkDebugCallback(VkDebugUtilsMessageSeverit
135135
return VK_FALSE;
136136
}
137137

138+
static std::pair<VkPhysicalDevice, uint32_t> resolveAdapter(const axstd::pod_vector<VkPhysicalDevice>& devices,
139+
VkInstance instance,
140+
PowerPreference pref)
141+
{
142+
VkPhysicalDevice bestDevice = VK_NULL_HANDLE;
143+
uint32_t graphicsQueueFamily = UINT32_MAX;
144+
int bestScore = -1;
145+
146+
for (auto pd : devices)
147+
{
148+
VkPhysicalDeviceProperties props{};
149+
vkGetPhysicalDeviceProperties(pd, &props);
150+
151+
uint32_t qCount = 0;
152+
vkGetPhysicalDeviceQueueFamilyProperties(pd, &qCount, nullptr);
153+
std::vector<VkQueueFamilyProperties> qprops(qCount);
154+
vkGetPhysicalDeviceQueueFamilyProperties(pd, &qCount, qprops.data());
155+
156+
bool hasGraphicsQueue = false;
157+
for (uint32_t i = 0; i < qCount; ++i)
158+
{
159+
if (qprops[i].queueCount > 0 && (qprops[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
160+
{
161+
hasGraphicsQueue = true;
162+
graphicsQueueFamily = i;
163+
break;
164+
}
165+
}
166+
if (!hasGraphicsQueue)
167+
continue; // skip devices without graphics queue
168+
169+
// --- Score device ---
170+
int score = 0;
171+
172+
// Power preference
173+
switch (pref)
174+
{
175+
case PowerPreference::HighPerformance:
176+
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
177+
score += 100;
178+
break;
179+
case PowerPreference::LowPower:
180+
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
181+
score += 100;
182+
break;
183+
case PowerPreference::Auto:
184+
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
185+
score += 50;
186+
else if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
187+
score += 25;
188+
break;
189+
}
190+
191+
// Prefer newer Vulkan versions
192+
score += static_cast<int>(props.apiVersion);
193+
194+
// Prefer larger VRAM (optional)
195+
VkPhysicalDeviceMemoryProperties memProps{};
196+
vkGetPhysicalDeviceMemoryProperties(pd, &memProps);
197+
VkDeviceSize vram = 0;
198+
for (uint32_t i = 0; i < memProps.memoryHeapCount; ++i)
199+
{
200+
if (memProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
201+
vram += memProps.memoryHeaps[i].size;
202+
}
203+
score += static_cast<int>(vram / (1024 * 1024 * 256)); // add points per 256MB
204+
205+
// --- Select best ---
206+
if (score > bestScore)
207+
{
208+
bestScore = score;
209+
bestDevice = pd;
210+
}
211+
}
212+
213+
return {bestDevice, graphicsQueueFamily};
214+
}
215+
138216
} // namespace
139217

140218
DriverImpl::DriverImpl() {}
@@ -147,29 +225,29 @@ DriverImpl::~DriverImpl()
147225
}
148226

149227
if (_surface)
150-
vkDestroySurfaceKHR(_vkInstance, _surface, nullptr);
228+
vkDestroySurfaceKHR(_factory, _surface, nullptr);
151229
if (_debugMessenger)
152-
vkDestroyDebugUtilsMessengerEXT(_vkInstance, _debugMessenger, nullptr);
230+
vkDestroyDebugUtilsMessengerEXT(_factory, _debugMessenger, nullptr);
153231
if (_device)
154232
vkDestroyDevice(_device, nullptr);
155-
if (_vkInstance)
156-
vkDestroyInstance(_vkInstance, nullptr);
233+
if (_factory)
234+
vkDestroyInstance(_factory, nullptr);
157235
}
158236

159237
void DriverImpl::init()
160238
{
161239
// Load basic Vulkan functions without instance/device
162240
gladLoaderLoadVulkan(nullptr, nullptr, nullptr);
163241

164-
initializeInstance();
242+
initializeFactory();
165243
initializeDevice();
166244

167245
// Load remaining Vulkan functions with instance/device
168-
gladLoaderLoadVulkan(_vkInstance, _physical, _device);
246+
gladLoaderLoadVulkan(_factory, _physical, _device);
169247

170248
if (_debugCreateInfo.sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT)
171249
{
172-
if (vkCreateDebugUtilsMessengerEXT(_vkInstance, &_debugCreateInfo, nullptr, &_debugMessenger) != VK_SUCCESS)
250+
if (vkCreateDebugUtilsMessengerEXT(_factory, &_debugCreateInfo, nullptr, &_debugMessenger) != VK_SUCCESS)
173251
{
174252
AXLOGW("Vulkan validation layer not available!");
175253
}
@@ -191,7 +269,7 @@ void DriverImpl::init()
191269
_caps.maxSamplesAllowed = static_cast<int32_t>(props.limits.framebufferColorSampleCounts);
192270
}
193271

194-
void DriverImpl::initializeInstance()
272+
void DriverImpl::initializeFactory()
195273
{
196274
auto& contextAttrs = Application::getContextAttrs();
197275

@@ -254,55 +332,26 @@ void DriverImpl::initializeInstance()
254332
}
255333

256334
// Instance layers/extensions are platform-dependent; keep minimal for core init
257-
VkResult vr = vkCreateInstance(&createInfo, nullptr, &_vkInstance);
258-
AXASSERT(vr == VK_SUCCESS && _vkInstance != VK_NULL_HANDLE, "vkCreateInstance failed");
259-
260-
// Select a physical device
261-
uint32_t count = 0;
262-
vkEnumeratePhysicalDevices(_vkInstance, &count, nullptr);
263-
AXASSERT(count > 0, "No Vulkan physical devices found");
264-
265-
std::vector<VkPhysicalDevice> devices(count);
266-
vkEnumeratePhysicalDevices(_vkInstance, &count, devices.data());
267-
268-
// Simple selection: first device with graphics queue
269-
_physical = VK_NULL_HANDLE;
270-
for (auto pd : devices)
271-
{
272-
uint32_t qCount = 0;
273-
vkGetPhysicalDeviceQueueFamilyProperties(pd, &qCount, nullptr);
274-
std::vector<VkQueueFamilyProperties> qprops(qCount);
275-
vkGetPhysicalDeviceQueueFamilyProperties(pd, &qCount, qprops.data());
276-
if (std::any_of(qprops.begin(), qprops.end(),
277-
[](const VkQueueFamilyProperties& p) { return (p.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0; }))
278-
{
279-
_physical = pd;
280-
break;
281-
}
282-
}
283-
if (_physical == VK_NULL_HANDLE)
284-
_physical = devices[0];
335+
VkResult vr = vkCreateInstance(&createInfo, nullptr, &_factory);
336+
AXASSERT(vr == VK_SUCCESS && _factory != VK_NULL_HANDLE, "vkCreateInstance failed");
285337
}
286338

287339
void DriverImpl::initializeDevice()
288340
{
289-
// find graphics queue family
290-
uint32_t queueCount = 0;
291-
vkGetPhysicalDeviceQueueFamilyProperties(_physical, &queueCount, nullptr);
292-
std::vector<VkQueueFamilyProperties> qprops(queueCount);
293-
vkGetPhysicalDeviceQueueFamilyProperties(_physical, &queueCount, qprops.data());
341+
auto& contextAttrs = Application::getContextAttrs();
294342

295-
_graphicsQueueFamily = UINT32_MAX;
296-
for (uint32_t i = 0; i < queueCount; ++i)
297-
{
298-
if (qprops[i].queueCount > 0 && (qprops[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
299-
{
300-
_graphicsQueueFamily = i;
301-
break;
302-
}
303-
}
343+
// Select a physical device
344+
uint32_t count = 0;
345+
vkEnumeratePhysicalDevices(_factory, &count, nullptr);
346+
AXASSERT(count > 0, "No Vulkan physical devices found");
347+
348+
axstd::pod_vector<VkPhysicalDevice> devices(count);
349+
vkEnumeratePhysicalDevices(_factory, &count, devices.data());
304350

305-
AXASSERT(_graphicsQueueFamily != UINT32_MAX, "No graphics queue family found");
351+
auto [physical, graphicsQueueFamily] = resolveAdapter(devices, _factory, contextAttrs.powerPreference);
352+
AXASSERT(physical != VK_NULL_HANDLE && graphicsQueueFamily != UINT32_MAX, "No available GPU");
353+
_physical = physical;
354+
_graphicsQueueFamily = graphicsQueueFamily;
306355

307356
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extDynState{};
308357
extDynState.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
@@ -345,7 +394,7 @@ void DriverImpl::initializeDevice()
345394

346395
bool DriverImpl::setupSurface(void* window, CreateSurfaceFunc func)
347396
{
348-
auto result = func(_vkInstance, window, &_surface);
397+
auto result = func(_factory, window, &_surface);
349398
if (result != VK_SUCCESS)
350399
return false;
351400

axmol/rhi/vulkan/DriverVK.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ class DriverImpl : public DriverBase
6868

6969
void waitIdle() override;
7070

71-
VkInstance getVkInstance() const { return _vkInstance; }
72-
VkPhysicalDevice getPhysicalDevice() const { return _physical; }
71+
VkPhysicalDevice getPhysical() const { return _physical; }
7372
VkDevice getDevice() const { return _device; }
7473

7574
VkQueue getGraphicsQueue() const { return _graphicsQueue; }
@@ -90,13 +89,13 @@ class DriverImpl : public DriverBase
9089
void destroySampler(SamplerHandle& h) override;
9190

9291
private:
93-
void initializeInstance();
92+
void initializeFactory();
9493
void initializeDevice();
9594

9695
VkDebugUtilsMessengerCreateInfoEXT _debugCreateInfo{};
9796
VkDebugUtilsMessengerEXT _debugMessenger{VK_NULL_HANDLE};
9897

99-
VkInstance _vkInstance{VK_NULL_HANDLE};
98+
VkInstance _factory{VK_NULL_HANDLE};
10099
VkPhysicalDevice _physical{VK_NULL_HANDLE};
101100
VkDevice _device{VK_NULL_HANDLE};
102101
VkSurfaceKHR _surface{VK_NULL_HANDLE};

0 commit comments

Comments
 (0)