Moved tool functions to vks namespace (Refs #260)
This commit is contained in:
parent
a105dfdece
commit
1309ee0ef9
34 changed files with 376 additions and 370 deletions
|
|
@ -13,7 +13,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "vulkan/vulkan.h"
|
||||
#include "vulkantools.h"
|
||||
#include "VulkanTools.h"
|
||||
|
||||
namespace vks
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include "vulkan/vulkan.h"
|
||||
#include "vulkantools.h"
|
||||
#include "VulkanTools.h"
|
||||
#include "VulkanBuffer.hpp"
|
||||
|
||||
namespace vks
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include <vector>
|
||||
#include "vulkan/vulkan.h"
|
||||
#include "VulkanDevice.hpp"
|
||||
#include "vulkantools.h"
|
||||
#include "VulkanTools.h"
|
||||
|
||||
namespace vks
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include <gli/gli.hpp>
|
||||
|
||||
#include "vulkantools.h"
|
||||
#include "VulkanTools.h"
|
||||
#include "VulkanDevice.hpp"
|
||||
#include "VulkanBuffer.hpp"
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ namespace vks
|
|||
|
||||
// Image barrier for optimal image (target)
|
||||
// Optimal image will be used as destination for the copy
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -236,7 +236,7 @@ namespace vks
|
|||
|
||||
// Change texture image layout to shader read after all mip levels have been copied
|
||||
this->imageLayout = imageLayout;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -320,7 +320,7 @@ namespace vks
|
|||
imageLayout = imageLayout;
|
||||
|
||||
// Setup image memory barrier
|
||||
vkTools::setImageLayout(copyCmd, image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, imageLayout);
|
||||
vks::tools::setImageLayout(copyCmd, image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, imageLayout);
|
||||
|
||||
device->flushCommandBuffer(copyCmd, copyQueue);
|
||||
}
|
||||
|
|
@ -477,7 +477,7 @@ namespace vks
|
|||
|
||||
// Image barrier for optimal image (target)
|
||||
// Optimal image will be used as destination for the copy
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -497,7 +497,7 @@ namespace vks
|
|||
|
||||
// Change texture image layout to shader read after all mip levels have been copied
|
||||
this->imageLayout = imageLayout;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -688,7 +688,7 @@ namespace vks
|
|||
subresourceRange.levelCount = mipLevels;
|
||||
subresourceRange.layerCount = layerCount;
|
||||
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -707,7 +707,7 @@ namespace vks
|
|||
|
||||
// Change texture image layout to shader read after all faces have been copied
|
||||
this->imageLayout = imageLayout;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -899,7 +899,7 @@ namespace vks
|
|||
subresourceRange.levelCount = mipLevels;
|
||||
subresourceRange.layerCount = 6;
|
||||
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -918,7 +918,7 @@ namespace vks
|
|||
|
||||
// Change texture image layout to shader read after all faces have been copied
|
||||
this->imageLayout = imageLayout;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
|
|||
|
|
@ -6,303 +6,278 @@
|
|||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||
*/
|
||||
|
||||
#include "vulkantools.h"
|
||||
#include "VulkanTools.h"
|
||||
|
||||
namespace vkTools
|
||||
namespace vks
|
||||
{
|
||||
std::string errorString(VkResult errorCode)
|
||||
namespace tools
|
||||
{
|
||||
switch (errorCode)
|
||||
std::string errorString(VkResult errorCode)
|
||||
{
|
||||
#define STR(r) case VK_ ##r: return #r
|
||||
STR(NOT_READY);
|
||||
STR(TIMEOUT);
|
||||
STR(EVENT_SET);
|
||||
STR(EVENT_RESET);
|
||||
STR(INCOMPLETE);
|
||||
STR(ERROR_OUT_OF_HOST_MEMORY);
|
||||
STR(ERROR_OUT_OF_DEVICE_MEMORY);
|
||||
STR(ERROR_INITIALIZATION_FAILED);
|
||||
STR(ERROR_DEVICE_LOST);
|
||||
STR(ERROR_MEMORY_MAP_FAILED);
|
||||
STR(ERROR_LAYER_NOT_PRESENT);
|
||||
STR(ERROR_EXTENSION_NOT_PRESENT);
|
||||
STR(ERROR_FEATURE_NOT_PRESENT);
|
||||
STR(ERROR_INCOMPATIBLE_DRIVER);
|
||||
STR(ERROR_TOO_MANY_OBJECTS);
|
||||
STR(ERROR_FORMAT_NOT_SUPPORTED);
|
||||
STR(ERROR_SURFACE_LOST_KHR);
|
||||
STR(ERROR_NATIVE_WINDOW_IN_USE_KHR);
|
||||
STR(SUBOPTIMAL_KHR);
|
||||
STR(ERROR_OUT_OF_DATE_KHR);
|
||||
STR(ERROR_INCOMPATIBLE_DISPLAY_KHR);
|
||||
STR(ERROR_VALIDATION_FAILED_EXT);
|
||||
STR(ERROR_INVALID_SHADER_NV);
|
||||
#undef STR
|
||||
default:
|
||||
return "UNKNOWN_ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
std::string physicalDeviceTypeString(VkPhysicalDeviceType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
#define STR(r) case VK_PHYSICAL_DEVICE_TYPE_ ##r: return #r
|
||||
STR(OTHER);
|
||||
STR(INTEGRATED_GPU);
|
||||
STR(DISCRETE_GPU);
|
||||
STR(VIRTUAL_GPU);
|
||||
#undef STR
|
||||
default: return "UNKNOWN_DEVICE_TYPE";
|
||||
}
|
||||
}
|
||||
|
||||
VkBool32 getSupportedDepthFormat(VkPhysicalDevice physicalDevice, VkFormat *depthFormat)
|
||||
{
|
||||
// Since all depth formats may be optional, we need to find a suitable depth format to use
|
||||
// Start with the highest precision packed format
|
||||
std::vector<VkFormat> depthFormats = {
|
||||
VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||
VK_FORMAT_D32_SFLOAT,
|
||||
VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
VK_FORMAT_D16_UNORM_S8_UINT,
|
||||
VK_FORMAT_D16_UNORM
|
||||
};
|
||||
|
||||
for (auto& format : depthFormats)
|
||||
{
|
||||
VkFormatProperties formatProps;
|
||||
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProps);
|
||||
// Format must support depth stencil attachment for optimal tiling
|
||||
if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||
switch (errorCode)
|
||||
{
|
||||
*depthFormat = format;
|
||||
return true;
|
||||
#define STR(r) case VK_ ##r: return #r
|
||||
STR(NOT_READY);
|
||||
STR(TIMEOUT);
|
||||
STR(EVENT_SET);
|
||||
STR(EVENT_RESET);
|
||||
STR(INCOMPLETE);
|
||||
STR(ERROR_OUT_OF_HOST_MEMORY);
|
||||
STR(ERROR_OUT_OF_DEVICE_MEMORY);
|
||||
STR(ERROR_INITIALIZATION_FAILED);
|
||||
STR(ERROR_DEVICE_LOST);
|
||||
STR(ERROR_MEMORY_MAP_FAILED);
|
||||
STR(ERROR_LAYER_NOT_PRESENT);
|
||||
STR(ERROR_EXTENSION_NOT_PRESENT);
|
||||
STR(ERROR_FEATURE_NOT_PRESENT);
|
||||
STR(ERROR_INCOMPATIBLE_DRIVER);
|
||||
STR(ERROR_TOO_MANY_OBJECTS);
|
||||
STR(ERROR_FORMAT_NOT_SUPPORTED);
|
||||
STR(ERROR_SURFACE_LOST_KHR);
|
||||
STR(ERROR_NATIVE_WINDOW_IN_USE_KHR);
|
||||
STR(SUBOPTIMAL_KHR);
|
||||
STR(ERROR_OUT_OF_DATE_KHR);
|
||||
STR(ERROR_INCOMPATIBLE_DISPLAY_KHR);
|
||||
STR(ERROR_VALIDATION_FAILED_EXT);
|
||||
STR(ERROR_INVALID_SHADER_NV);
|
||||
#undef STR
|
||||
default:
|
||||
return "UNKNOWN_ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create an image memory barrier for changing the layout of
|
||||
// an image and put it into an active command buffer
|
||||
// See chapter 11.4 "Image Layout" for details
|
||||
|
||||
void setImageLayout(
|
||||
VkCommandBuffer cmdbuffer,
|
||||
VkImage image,
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkImageSubresourceRange subresourceRange,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask)
|
||||
{
|
||||
// Create an image barrier object
|
||||
VkImageMemoryBarrier imageMemoryBarrier = vks::initializers::imageMemoryBarrier();
|
||||
imageMemoryBarrier.oldLayout = oldImageLayout;
|
||||
imageMemoryBarrier.newLayout = newImageLayout;
|
||||
imageMemoryBarrier.image = image;
|
||||
imageMemoryBarrier.subresourceRange = subresourceRange;
|
||||
|
||||
// Source layouts (old)
|
||||
// Source access mask controls actions that have to be finished on the old layout
|
||||
// before it will be transitioned to the new layout
|
||||
switch (oldImageLayout)
|
||||
std::string physicalDeviceTypeString(VkPhysicalDeviceType type)
|
||||
{
|
||||
case VK_IMAGE_LAYOUT_UNDEFINED:
|
||||
switch (type)
|
||||
{
|
||||
#define STR(r) case VK_PHYSICAL_DEVICE_TYPE_ ##r: return #r
|
||||
STR(OTHER);
|
||||
STR(INTEGRATED_GPU);
|
||||
STR(DISCRETE_GPU);
|
||||
STR(VIRTUAL_GPU);
|
||||
#undef STR
|
||||
default: return "UNKNOWN_DEVICE_TYPE";
|
||||
}
|
||||
}
|
||||
|
||||
VkBool32 getSupportedDepthFormat(VkPhysicalDevice physicalDevice, VkFormat *depthFormat)
|
||||
{
|
||||
// Since all depth formats may be optional, we need to find a suitable depth format to use
|
||||
// Start with the highest precision packed format
|
||||
std::vector<VkFormat> depthFormats = {
|
||||
VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||
VK_FORMAT_D32_SFLOAT,
|
||||
VK_FORMAT_D24_UNORM_S8_UINT,
|
||||
VK_FORMAT_D16_UNORM_S8_UINT,
|
||||
VK_FORMAT_D16_UNORM
|
||||
};
|
||||
|
||||
for (auto& format : depthFormats)
|
||||
{
|
||||
VkFormatProperties formatProps;
|
||||
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProps);
|
||||
// Format must support depth stencil attachment for optimal tiling
|
||||
if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
|
||||
{
|
||||
*depthFormat = format;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create an image memory barrier for changing the layout of
|
||||
// an image and put it into an active command buffer
|
||||
// See chapter 11.4 "Image Layout" for details
|
||||
|
||||
void setImageLayout(
|
||||
VkCommandBuffer cmdbuffer,
|
||||
VkImage image,
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkImageSubresourceRange subresourceRange,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask)
|
||||
{
|
||||
// Create an image barrier object
|
||||
VkImageMemoryBarrier imageMemoryBarrier = vks::initializers::imageMemoryBarrier();
|
||||
imageMemoryBarrier.oldLayout = oldImageLayout;
|
||||
imageMemoryBarrier.newLayout = newImageLayout;
|
||||
imageMemoryBarrier.image = image;
|
||||
imageMemoryBarrier.subresourceRange = subresourceRange;
|
||||
|
||||
// Source layouts (old)
|
||||
// Source access mask controls actions that have to be finished on the old layout
|
||||
// before it will be transitioned to the new layout
|
||||
switch (oldImageLayout)
|
||||
{
|
||||
case VK_IMAGE_LAYOUT_UNDEFINED:
|
||||
// Image layout is undefined (or does not matter)
|
||||
// Only valid as initial layout
|
||||
// No flags required, listed only for completeness
|
||||
imageMemoryBarrier.srcAccessMask = 0;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_PREINITIALIZED:
|
||||
case VK_IMAGE_LAYOUT_PREINITIALIZED:
|
||||
// Image is preinitialized
|
||||
// Only valid as initial layout for linear images, preserves memory contents
|
||||
// Make sure host writes have been finished
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
// Image is a color attachment
|
||||
// Make sure any writes to the color buffer have been finished
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
// Image is a depth/stencil attachment
|
||||
// Make sure any writes to the depth/stencil buffer have been finished
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
||||
// Image is a transfer source
|
||||
// Make sure any reads from the image have been finished
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
||||
// Image is a transfer destination
|
||||
// Make sure any writes to the image have been finished
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
// Image is read by a shader
|
||||
// Make sure any shader reads from the image have been finished
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Target layouts (new)
|
||||
// Destination access mask controls the dependency for the new image layout
|
||||
switch (newImageLayout)
|
||||
{
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
||||
// Image will be used as a transfer destination
|
||||
// Make sure any writes to the image have been finished
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
||||
// Image will be used as a transfer source
|
||||
// Make sure any reads from and writes to the image have been finished
|
||||
imageMemoryBarrier.srcAccessMask = imageMemoryBarrier.srcAccessMask | VK_ACCESS_TRANSFER_READ_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
// Image will be used as a color attachment
|
||||
// Make sure any writes to the color buffer have been finished
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
// Image layout will be used as a depth/stencil attachment
|
||||
// Make sure any writes to depth/stencil buffer have been finished
|
||||
imageMemoryBarrier.dstAccessMask = imageMemoryBarrier.dstAccessMask | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
// Image will be read in a shader (sampler, input attachment)
|
||||
// Make sure any writes to the image have been finished
|
||||
if (imageMemoryBarrier.srcAccessMask == 0)
|
||||
{
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
}
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
break;
|
||||
|
||||
// Target layouts (new)
|
||||
// Destination access mask controls the dependency for the new image layout
|
||||
switch (newImageLayout)
|
||||
{
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
||||
// Image will be used as a transfer destination
|
||||
// Make sure any writes to the image have been finished
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
||||
// Image will be used as a transfer source
|
||||
// Make sure any reads from and writes to the image have been finished
|
||||
imageMemoryBarrier.srcAccessMask = imageMemoryBarrier.srcAccessMask | VK_ACCESS_TRANSFER_READ_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
// Image will be used as a color attachment
|
||||
// Make sure any writes to the color buffer have been finished
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
||||
// Image layout will be used as a depth/stencil attachment
|
||||
// Make sure any writes to depth/stencil buffer have been finished
|
||||
imageMemoryBarrier.dstAccessMask = imageMemoryBarrier.dstAccessMask | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
// Image will be read in a shader (sampler, input attachment)
|
||||
// Make sure any writes to the image have been finished
|
||||
if (imageMemoryBarrier.srcAccessMask == 0)
|
||||
{
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
}
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Put barrier inside setup command buffer
|
||||
vkCmdPipelineBarrier(
|
||||
cmdbuffer,
|
||||
srcStageMask,
|
||||
dstStageMask,
|
||||
0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &imageMemoryBarrier);
|
||||
}
|
||||
|
||||
// Put barrier inside setup command buffer
|
||||
vkCmdPipelineBarrier(
|
||||
cmdbuffer,
|
||||
srcStageMask,
|
||||
dstStageMask,
|
||||
0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &imageMemoryBarrier);
|
||||
}
|
||||
// Fixed sub resource on first mip level and layer
|
||||
void setImageLayout(
|
||||
VkCommandBuffer cmdbuffer,
|
||||
VkImage image,
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask)
|
||||
{
|
||||
VkImageSubresourceRange subresourceRange = {};
|
||||
subresourceRange.aspectMask = aspectMask;
|
||||
subresourceRange.baseMipLevel = 0;
|
||||
subresourceRange.levelCount = 1;
|
||||
subresourceRange.layerCount = 1;
|
||||
setImageLayout(cmdbuffer, image, aspectMask, oldImageLayout, newImageLayout, subresourceRange);
|
||||
}
|
||||
|
||||
// Fixed sub resource on first mip level and layer
|
||||
void setImageLayout(
|
||||
VkCommandBuffer cmdbuffer,
|
||||
VkImage image,
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask)
|
||||
{
|
||||
VkImageSubresourceRange subresourceRange = {};
|
||||
subresourceRange.aspectMask = aspectMask;
|
||||
subresourceRange.baseMipLevel = 0;
|
||||
subresourceRange.levelCount = 1;
|
||||
subresourceRange.layerCount = 1;
|
||||
setImageLayout(cmdbuffer, image, aspectMask, oldImageLayout, newImageLayout, subresourceRange);
|
||||
}
|
||||
|
||||
void exitFatal(std::string message, std::string caption)
|
||||
{
|
||||
void exitFatal(std::string message, std::string caption)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
MessageBox(NULL, message.c_str(), caption.c_str(), MB_OK | MB_ICONERROR);
|
||||
MessageBox(NULL, message.c_str(), caption.c_str(), MB_OK | MB_ICONERROR);
|
||||
#else
|
||||
// TODO : Linux
|
||||
// TODO : Linux
|
||||
#endif
|
||||
std::cerr << message << "\n";
|
||||
exit(1);
|
||||
}
|
||||
std::cerr << message << "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string readTextFile(const char *fileName)
|
||||
{
|
||||
std::string fileContent;
|
||||
std::ifstream fileStream(fileName, std::ios::in);
|
||||
if (!fileStream.is_open()) {
|
||||
printf("File %s not found\n", fileName);
|
||||
return "";
|
||||
std::string readTextFile(const char *fileName)
|
||||
{
|
||||
std::string fileContent;
|
||||
std::ifstream fileStream(fileName, std::ios::in);
|
||||
if (!fileStream.is_open()) {
|
||||
printf("File %s not found\n", fileName);
|
||||
return "";
|
||||
}
|
||||
std::string line = "";
|
||||
while (!fileStream.eof()) {
|
||||
getline(fileStream, line);
|
||||
fileContent.append(line + "\n");
|
||||
}
|
||||
fileStream.close();
|
||||
return fileContent;
|
||||
}
|
||||
std::string line = "";
|
||||
while (!fileStream.eof()) {
|
||||
getline(fileStream, line);
|
||||
fileContent.append(line + "\n");
|
||||
}
|
||||
fileStream.close();
|
||||
return fileContent;
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// Android shaders are stored as assets in the apk
|
||||
// So they need to be loaded via the asset manager
|
||||
VkShaderModule loadShader(AAssetManager* assetManager, const char *fileName, VkDevice device, VkShaderStageFlagBits stage)
|
||||
{
|
||||
// Load shader from compressed asset
|
||||
AAsset* asset = AAssetManager_open(assetManager, fileName, AASSET_MODE_STREAMING);
|
||||
assert(asset);
|
||||
size_t size = AAsset_getLength(asset);
|
||||
assert(size > 0);
|
||||
|
||||
char *shaderCode = new char[size];
|
||||
AAsset_read(asset, shaderCode, size);
|
||||
AAsset_close(asset);
|
||||
|
||||
VkShaderModule shaderModule;
|
||||
VkShaderModuleCreateInfo moduleCreateInfo;
|
||||
moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
moduleCreateInfo.pNext = NULL;
|
||||
moduleCreateInfo.codeSize = size;
|
||||
moduleCreateInfo.pCode = (uint32_t*)shaderCode;
|
||||
moduleCreateInfo.flags = 0;
|
||||
|
||||
VK_CHECK_RESULT(vkCreateShaderModule(device, &moduleCreateInfo, NULL, &shaderModule));
|
||||
|
||||
delete[] shaderCode;
|
||||
|
||||
return shaderModule;
|
||||
}
|
||||
#else
|
||||
VkShaderModule loadShader(const char *fileName, VkDevice device, VkShaderStageFlagBits stage)
|
||||
{
|
||||
std::ifstream is(fileName, std::ios::binary | std::ios::in | std::ios::ate);
|
||||
|
||||
if (is.is_open())
|
||||
// Android shaders are stored as assets in the apk
|
||||
// So they need to be loaded via the asset manager
|
||||
VkShaderModule loadShader(AAssetManager* assetManager, const char *fileName, VkDevice device, VkShaderStageFlagBits stage)
|
||||
{
|
||||
size_t size = is.tellg();
|
||||
is.seekg(0, std::ios::beg);
|
||||
char* shaderCode = new char[size];
|
||||
is.read(shaderCode, size);
|
||||
is.close();
|
||||
|
||||
// Load shader from compressed asset
|
||||
AAsset* asset = AAssetManager_open(assetManager, fileName, AASSET_MODE_STREAMING);
|
||||
assert(asset);
|
||||
size_t size = AAsset_getLength(asset);
|
||||
assert(size > 0);
|
||||
|
||||
char *shaderCode = new char[size];
|
||||
AAsset_read(asset, shaderCode, size);
|
||||
AAsset_close(asset);
|
||||
|
||||
VkShaderModule shaderModule;
|
||||
VkShaderModuleCreateInfo moduleCreateInfo{};
|
||||
VkShaderModuleCreateInfo moduleCreateInfo;
|
||||
moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
moduleCreateInfo.pNext = NULL;
|
||||
moduleCreateInfo.codeSize = size;
|
||||
moduleCreateInfo.pCode = (uint32_t*)shaderCode;
|
||||
moduleCreateInfo.flags = 0;
|
||||
|
||||
VK_CHECK_RESULT(vkCreateShaderModule(device, &moduleCreateInfo, NULL, &shaderModule));
|
||||
|
||||
|
|
@ -310,37 +285,65 @@ namespace vkTools
|
|||
|
||||
return shaderModule;
|
||||
}
|
||||
else
|
||||
#else
|
||||
VkShaderModule loadShader(const char *fileName, VkDevice device, VkShaderStageFlagBits stage)
|
||||
{
|
||||
std::cerr << "Error: Could not open shader file \"" << fileName << "\"" << std::endl;
|
||||
return nullptr;
|
||||
std::ifstream is(fileName, std::ios::binary | std::ios::in | std::ios::ate);
|
||||
|
||||
if (is.is_open())
|
||||
{
|
||||
size_t size = is.tellg();
|
||||
is.seekg(0, std::ios::beg);
|
||||
char* shaderCode = new char[size];
|
||||
is.read(shaderCode, size);
|
||||
is.close();
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
VkShaderModule shaderModule;
|
||||
VkShaderModuleCreateInfo moduleCreateInfo{};
|
||||
moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
moduleCreateInfo.codeSize = size;
|
||||
moduleCreateInfo.pCode = (uint32_t*)shaderCode;
|
||||
|
||||
VK_CHECK_RESULT(vkCreateShaderModule(device, &moduleCreateInfo, NULL, &shaderModule));
|
||||
|
||||
delete[] shaderCode;
|
||||
|
||||
return shaderModule;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: Could not open shader file \"" << fileName << "\"" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
VkShaderModule loadShaderGLSL(const char *fileName, VkDevice device, VkShaderStageFlagBits stage)
|
||||
{
|
||||
std::string shaderSrc = readTextFile(fileName);
|
||||
const char *shaderCode = shaderSrc.c_str();
|
||||
size_t size = strlen(shaderCode);
|
||||
assert(size > 0);
|
||||
VkShaderModule loadShaderGLSL(const char *fileName, VkDevice device, VkShaderStageFlagBits stage)
|
||||
{
|
||||
std::string shaderSrc = readTextFile(fileName);
|
||||
const char *shaderCode = shaderSrc.c_str();
|
||||
size_t size = strlen(shaderCode);
|
||||
assert(size > 0);
|
||||
|
||||
VkShaderModule shaderModule;
|
||||
VkShaderModuleCreateInfo moduleCreateInfo;
|
||||
moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
moduleCreateInfo.pNext = NULL;
|
||||
moduleCreateInfo.codeSize = 3 * sizeof(uint32_t) + size + 1;
|
||||
moduleCreateInfo.pCode = (uint32_t*)malloc(moduleCreateInfo.codeSize);
|
||||
moduleCreateInfo.flags = 0;
|
||||
VkShaderModule shaderModule;
|
||||
VkShaderModuleCreateInfo moduleCreateInfo;
|
||||
moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
moduleCreateInfo.pNext = NULL;
|
||||
moduleCreateInfo.codeSize = 3 * sizeof(uint32_t) + size + 1;
|
||||
moduleCreateInfo.pCode = (uint32_t*)malloc(moduleCreateInfo.codeSize);
|
||||
moduleCreateInfo.flags = 0;
|
||||
|
||||
// Magic SPV number
|
||||
((uint32_t *)moduleCreateInfo.pCode)[0] = 0x07230203;
|
||||
((uint32_t *)moduleCreateInfo.pCode)[1] = 0;
|
||||
((uint32_t *)moduleCreateInfo.pCode)[2] = stage;
|
||||
memcpy(((uint32_t *)moduleCreateInfo.pCode + 3), shaderCode, size + 1);
|
||||
// Magic SPV number
|
||||
((uint32_t *)moduleCreateInfo.pCode)[0] = 0x07230203;
|
||||
((uint32_t *)moduleCreateInfo.pCode)[1] = 0;
|
||||
((uint32_t *)moduleCreateInfo.pCode)[2] = stage;
|
||||
memcpy(((uint32_t *)moduleCreateInfo.pCode + 3), shaderCode, size + 1);
|
||||
|
||||
VK_CHECK_RESULT(vkCreateShaderModule(device, &moduleCreateInfo, NULL, &shaderModule));
|
||||
VK_CHECK_RESULT(vkCreateShaderModule(device, &moduleCreateInfo, NULL, &shaderModule));
|
||||
|
||||
return shaderModule;
|
||||
return shaderModule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
VkResult res = (f); \
|
||||
if (res != VK_SUCCESS) \
|
||||
{ \
|
||||
LOGE("Fatal : VkResult is \" %s \" in %s at line %d", vkTools::errorString(res).c_str(), __FILE__, __LINE__); \
|
||||
LOGE("Fatal : VkResult is \" %s \" in %s at line %d", vks::tools::errorString(res).c_str(), __FILE__, __LINE__); \
|
||||
assert(res == VK_SUCCESS); \
|
||||
} \
|
||||
}
|
||||
|
|
@ -52,55 +52,58 @@
|
|||
VkResult res = (f); \
|
||||
if (res != VK_SUCCESS) \
|
||||
{ \
|
||||
std::cout << "Fatal : VkResult is \"" << vkTools::errorString(res) << "\" in " << __FILE__ << " at line " << __LINE__ << std::endl; \
|
||||
std::cout << "Fatal : VkResult is \"" << vks::tools::errorString(res) << "\" in " << __FILE__ << " at line " << __LINE__ << std::endl; \
|
||||
assert(res == VK_SUCCESS); \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace vkTools
|
||||
namespace vks
|
||||
{
|
||||
/** @brief Returns an error code as a string */
|
||||
std::string errorString(VkResult errorCode);
|
||||
namespace tools
|
||||
{
|
||||
/** @brief Returns an error code as a string */
|
||||
std::string errorString(VkResult errorCode);
|
||||
|
||||
/** @brief Returns the device type as a string */
|
||||
std::string physicalDeviceTypeString(VkPhysicalDeviceType type);
|
||||
/** @brief Returns the device type as a string */
|
||||
std::string physicalDeviceTypeString(VkPhysicalDeviceType type);
|
||||
|
||||
// Selected a suitable supported depth format starting with 32 bit down to 16 bit
|
||||
// Returns false if none of the depth formats in the list is supported by the device
|
||||
VkBool32 getSupportedDepthFormat(VkPhysicalDevice physicalDevice, VkFormat *depthFormat);
|
||||
// Selected a suitable supported depth format starting with 32 bit down to 16 bit
|
||||
// Returns false if none of the depth formats in the list is supported by the device
|
||||
VkBool32 getSupportedDepthFormat(VkPhysicalDevice physicalDevice, VkFormat *depthFormat);
|
||||
|
||||
// Put an image memory barrier for setting an image layout on the sub resource into the given command buffer
|
||||
void setImageLayout(
|
||||
VkCommandBuffer cmdbuffer,
|
||||
VkImage image,
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkImageSubresourceRange subresourceRange,
|
||||
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||
// Uses a fixed sub resource layout with first mip level and layer
|
||||
void setImageLayout(
|
||||
VkCommandBuffer cmdbuffer,
|
||||
VkImage image,
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||
// Put an image memory barrier for setting an image layout on the sub resource into the given command buffer
|
||||
void setImageLayout(
|
||||
VkCommandBuffer cmdbuffer,
|
||||
VkImage image,
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkImageSubresourceRange subresourceRange,
|
||||
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||
// Uses a fixed sub resource layout with first mip level and layer
|
||||
void setImageLayout(
|
||||
VkCommandBuffer cmdbuffer,
|
||||
VkImage image,
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||
|
||||
// Display error message and exit on fatal error
|
||||
void exitFatal(std::string message, std::string caption);
|
||||
// Display error message and exit on fatal error
|
||||
void exitFatal(std::string message, std::string caption);
|
||||
|
||||
// Load a SPIR-V shader (binary)
|
||||
// Load a SPIR-V shader (binary)
|
||||
#if defined(__ANDROID__)
|
||||
VkShaderModule loadShader(AAssetManager* assetManager, const char *fileName, VkDevice device, VkShaderStageFlagBits stage);
|
||||
VkShaderModule loadShader(AAssetManager* assetManager, const char *fileName, VkDevice device, VkShaderStageFlagBits stage);
|
||||
#else
|
||||
VkShaderModule loadShader(const char *fileName, VkDevice device, VkShaderStageFlagBits stage);
|
||||
VkShaderModule loadShader(const char *fileName, VkDevice device, VkShaderStageFlagBits stage);
|
||||
#endif
|
||||
|
||||
// Load a GLSL shader (text)
|
||||
// Note: GLSL support requires vendor-specific extensions to be enabled and is not a core-feature of Vulkan
|
||||
VkShaderModule loadShaderGLSL(const char *fileName, VkDevice device, VkShaderStageFlagBits stage);
|
||||
// Load a GLSL shader (text)
|
||||
// Note: GLSL support requires vendor-specific extensions to be enabled and is not a core-feature of Vulkan
|
||||
VkShaderModule loadShaderGLSL(const char *fileName, VkDevice device, VkShaderStageFlagBits stage);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,9 +200,9 @@ VkPipelineShaderStageCreateInfo VulkanExampleBase::loadShader(std::string fileNa
|
|||
shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
shaderStage.stage = stage;
|
||||
#if defined(__ANDROID__)
|
||||
shaderStage.module = vkTools::loadShader(androidApp->activity->assetManager, fileName.c_str(), device, stage);
|
||||
shaderStage.module = vks::tools::loadShader(androidApp->activity->assetManager, fileName.c_str(), device, stage);
|
||||
#else
|
||||
shaderStage.module = vkTools::loadShader(fileName.c_str(), device, stage);
|
||||
shaderStage.module = vks::tools::loadShader(fileName.c_str(), device, stage);
|
||||
#endif
|
||||
shaderStage.pName = "main"; // todo : make param
|
||||
assert(shaderStage.module != NULL);
|
||||
|
|
@ -721,7 +721,7 @@ void VulkanExampleBase::initVulkan()
|
|||
err = createInstance(settings.validation);
|
||||
if (err)
|
||||
{
|
||||
vkTools::exitFatal("Could not create Vulkan instance : \n" + vkTools::errorString(err), "Fatal error");
|
||||
vks::tools::exitFatal("Could not create Vulkan instance : \n" + vks::tools::errorString(err), "Fatal error");
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
|
@ -748,7 +748,7 @@ void VulkanExampleBase::initVulkan()
|
|||
err = vkEnumeratePhysicalDevices(instance, &gpuCount, physicalDevices.data());
|
||||
if (err)
|
||||
{
|
||||
vkTools::exitFatal("Could not enumerate physical devices : \n" + vkTools::errorString(err), "Fatal error");
|
||||
vks::tools::exitFatal("Could not enumerate physical devices : \n" + vks::tools::errorString(err), "Fatal error");
|
||||
}
|
||||
|
||||
// GPU selection
|
||||
|
|
@ -799,7 +799,7 @@ void VulkanExampleBase::initVulkan()
|
|||
VkPhysicalDeviceProperties deviceProperties;
|
||||
vkGetPhysicalDeviceProperties(devices[i], &deviceProperties);
|
||||
std::cout << "Device [" << i << "] : " << deviceProperties.deviceName << std::endl;
|
||||
std::cout << " Type: " << vkTools::physicalDeviceTypeString(deviceProperties.deviceType) << std::endl;
|
||||
std::cout << " Type: " << vks::tools::physicalDeviceTypeString(deviceProperties.deviceType) << std::endl;
|
||||
std::cout << " API: " << (deviceProperties.apiVersion >> 22) << "." << ((deviceProperties.apiVersion >> 12) & 0x3ff) << "." << (deviceProperties.apiVersion & 0xfff) << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
@ -815,7 +815,7 @@ void VulkanExampleBase::initVulkan()
|
|||
vulkanDevice = new vks::VulkanDevice(physicalDevice);
|
||||
VkResult res = vulkanDevice->createLogicalDevice(enabledFeatures, enabledExtensions);
|
||||
if (res != VK_SUCCESS) {
|
||||
vkTools::exitFatal("Could not create Vulkan device: \n" + vkTools::errorString(res), "Fatal error");
|
||||
vks::tools::exitFatal("Could not create Vulkan device: \n" + vks::tools::errorString(res), "Fatal error");
|
||||
}
|
||||
device = vulkanDevice->logicalDevice;
|
||||
|
||||
|
|
@ -831,7 +831,7 @@ void VulkanExampleBase::initVulkan()
|
|||
vkGetDeviceQueue(device, vulkanDevice->queueFamilyIndices.graphics, 0, &queue);
|
||||
|
||||
// Find a suitable depth format
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &depthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &depthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
swapChain.connect(instance, physicalDevice, device);
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
#include "vulkan/vulkan.h"
|
||||
|
||||
#include "keycodes.hpp"
|
||||
#include "vulkantools.h"
|
||||
#include "VulkanTools.h"
|
||||
#include "VulkanDebug.h"
|
||||
|
||||
#include "VulkanInitializers.hpp"
|
||||
|
|
@ -127,7 +127,7 @@ protected:
|
|||
VkSemaphore textOverlayComplete;
|
||||
} semaphores;
|
||||
// Simple texture loader
|
||||
//vkTools::VulkanTextureLoader *textureLoader = nullptr;
|
||||
//vks::tools::VulkanTextureLoader *textureLoader = nullptr;
|
||||
// Returns the base asset path (for shaders, models, textures) depending on the os
|
||||
const std::string getAssetPath();
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#endif
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "vulkantools.h"
|
||||
#include "VulkanTools.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "vulkanandroid.h"
|
||||
|
|
@ -211,13 +211,13 @@ public:
|
|||
// Exit if either a graphics or a presenting queue hasn't been found
|
||||
if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX)
|
||||
{
|
||||
vkTools::exitFatal("Could not find a graphics and/or presenting queue!", "Fatal error");
|
||||
vks::tools::exitFatal("Could not find a graphics and/or presenting queue!", "Fatal error");
|
||||
}
|
||||
|
||||
// todo : Add support for separate graphics and presenting queue
|
||||
if (graphicsQueueNodeIndex != presentQueueNodeIndex)
|
||||
{
|
||||
vkTools::exitFatal("Separate graphics and presenting queues are not supported yet!", "Fatal error");
|
||||
vks::tools::exitFatal("Separate graphics and presenting queues are not supported yet!", "Fatal error");
|
||||
}
|
||||
|
||||
queueNodeIndex = graphicsQueueNodeIndex;
|
||||
|
|
@ -576,7 +576,7 @@ public:
|
|||
|
||||
if(!foundMode)
|
||||
{
|
||||
vkTools::exitFatal("Can't find a display and a display mode!", "Fatal error");
|
||||
vks::tools::exitFatal("Can't find a display and a display mode!", "Fatal error");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -613,7 +613,7 @@ public:
|
|||
|
||||
if(bestPlaneIndex == UINT32_MAX)
|
||||
{
|
||||
vkTools::exitFatal("Can't find a plane for displaying!", "Fatal error");
|
||||
vks::tools::exitFatal("Can't find a plane for displaying!", "Fatal error");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -651,7 +651,7 @@ public:
|
|||
VkResult result = vkCreateDisplayPlaneSurfaceKHR(instance, &surfaceInfo, NULL, &surface);
|
||||
if(result !=VK_SUCCESS)
|
||||
{
|
||||
vkTools::exitFatal("Failed to create surface!", "Fatal error");
|
||||
vks::tools::exitFatal("Failed to create surface!", "Fatal error");
|
||||
}
|
||||
|
||||
delete[] pDisplays;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include <iomanip>
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include "vulkantools.h"
|
||||
#include "VulkanTools.h"
|
||||
#include "VulkanDebug.h"
|
||||
#include "VulkanBuffer.hpp"
|
||||
#include "VulkanDevice.hpp"
|
||||
|
|
@ -224,7 +224,7 @@ public:
|
|||
VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo));
|
||||
|
||||
// Prepare for transfer
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -249,7 +249,7 @@ public:
|
|||
);
|
||||
|
||||
// Prepare for shader read
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ public:
|
|||
|
||||
// Find a suitable depth format
|
||||
VkFormat fbDepthFormat;
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
// Create a separate render pass for the offscreen rendering as it may differ from the one used for scene rendering
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ public:
|
|||
VkCommandBuffer layoutCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
|
||||
tex->imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
layoutCmd, tex->image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ public:
|
|||
|
||||
// Find a suitable depth format
|
||||
VkFormat fbDepthFormat;
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
// Color attachment
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ public:
|
|||
|
||||
// Find a suitable depth format
|
||||
VkFormat attDepthFormat;
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &attDepthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attDepthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
createAttachment(
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ public:
|
|||
|
||||
// Find a suitable depth format
|
||||
VkFormat attDepthFormat;
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &attDepthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attDepthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
createAttachment(
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ public:
|
|||
VK_CHECK_RESULT(frameBuffers.shadow->createRenderPass());
|
||||
|
||||
VkCommandBuffer cmdBuf = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
cmdBuf,
|
||||
frameBuffers.shadow->attachments[0].image,
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
|
||||
|
|
@ -303,7 +303,7 @@ public:
|
|||
// Depth attachment
|
||||
// Find a suitable depth format
|
||||
VkFormat attDepthFormat;
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &attDepthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attDepthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
attachmentInfo.format = attDepthFormat;
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@ public:
|
|||
// Check if device supports tessellation shaders
|
||||
if (!deviceFeatures.tessellationShader)
|
||||
{
|
||||
vkTools::exitFatal("Selected GPU does not support tessellation shaders!", "Feature not supported");
|
||||
vks::tools::exitFatal("Selected GPU does not support tessellation shaders!", "Feature not supported");
|
||||
}
|
||||
|
||||
VulkanExampleBase::prepare();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "vulkan/vulkan.h"
|
||||
|
||||
#include "vulkantools.h"
|
||||
#include "VulkanTools.h"
|
||||
#include "VulkanDevice.hpp"
|
||||
#include "VulkanBuffer.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ public:
|
|||
|
||||
// Find a suitable depth format
|
||||
VkFormat fbDepthFormat;
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
// Color attachment
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ public:
|
|||
|
||||
// Find a suitable depth format
|
||||
VkFormat fbDepthFormat;
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
// Color attachment
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ public:
|
|||
VkCommandBuffer layoutCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
|
||||
tex->imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
layoutCmd,
|
||||
tex->image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ public:
|
|||
VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
|
||||
// Transition destination image to transfer destination layout
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
dstImage,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -402,7 +402,7 @@ public:
|
|||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
// Transition swapchain image from present to transfer source layout
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
srcImage,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -434,7 +434,7 @@ public:
|
|||
VK_FILTER_NEAREST);
|
||||
|
||||
// Transition destination image to general layout, which is the required layout for mapping the image memory later on
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
dstImage,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -444,7 +444,7 @@ public:
|
|||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
// Transition back the swap chain image after the blit is done
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
srcImage,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ public:
|
|||
subresourceRange.baseMipLevel = 0;
|
||||
subresourceRange.levelCount = 1;
|
||||
subresourceRange.layerCount = 6;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
layoutCmd,
|
||||
shadowCubeMap.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -312,7 +312,7 @@ public:
|
|||
|
||||
VkCommandBuffer layoutCmd = VulkanExampleBase::createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
layoutCmd,
|
||||
offscreenPass.color.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -344,7 +344,7 @@ public:
|
|||
VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &offscreenPass.depth.mem));
|
||||
VK_CHECK_RESULT(vkBindImageMemory(device, offscreenPass.depth.image, offscreenPass.depth.mem, 0));
|
||||
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
layoutCmd,
|
||||
offscreenPass.depth.image,
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
|
||||
|
|
@ -441,7 +441,7 @@ public:
|
|||
|
||||
vkCmdEndRenderPass(offscreenPass.commandBuffer);
|
||||
// Make sure color writes to the framebuffer are finished before using it as transfer source
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
offscreenPass.commandBuffer,
|
||||
offscreenPass.color.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -478,7 +478,7 @@ public:
|
|||
©Region);
|
||||
|
||||
// Transform framebuffer color attachment back
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
offscreenPass.commandBuffer,
|
||||
offscreenPass.color.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -517,7 +517,7 @@ public:
|
|||
subresourceRange.layerCount = 6;
|
||||
|
||||
// Change image layout for all cubemap faces to transfer destination
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
offscreenPass.commandBuffer,
|
||||
shadowCubeMap.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -531,7 +531,7 @@ public:
|
|||
}
|
||||
|
||||
// Change image layout for all cubemap faces to shader read after they have been copied
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
offscreenPass.commandBuffer,
|
||||
shadowCubeMap.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -794,7 +794,7 @@ public:
|
|||
VkAttachmentDescription osAttachments[2] = {};
|
||||
|
||||
// Find a suitable depth format
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &fbDepthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
osAttachments[0].format = FB_COLOR_FORMAT;
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ public:
|
|||
|
||||
// Find a suitable depth format
|
||||
VkFormat attDepthFormat;
|
||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &attDepthFormat);
|
||||
VkBool32 validDepthFormat = vks::tools::getSupportedDepthFormat(physicalDevice, &attDepthFormat);
|
||||
assert(validDepthFormat);
|
||||
|
||||
// G-Buffer
|
||||
|
|
|
|||
|
|
@ -879,7 +879,7 @@ public:
|
|||
// Check if device supports tessellation shaders
|
||||
if (!deviceFeatures.tessellationShader)
|
||||
{
|
||||
vkTools::exitFatal("Selected GPU does not support tessellation shaders!", "Feature not supported");
|
||||
vks::tools::exitFatal("Selected GPU does not support tessellation shaders!", "Feature not supported");
|
||||
}
|
||||
|
||||
VulkanExampleBase::prepare();
|
||||
|
|
|
|||
|
|
@ -489,7 +489,7 @@ public:
|
|||
// Check if device supports tessellation shaders
|
||||
if (!deviceFeatures.tessellationShader)
|
||||
{
|
||||
vkTools::exitFatal("Selected GPU does not support tessellation shaders!", "Feature not supported");
|
||||
vks::tools::exitFatal("Selected GPU does not support tessellation shaders!", "Feature not supported");
|
||||
}
|
||||
|
||||
VulkanExampleBase::prepare();
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ public:
|
|||
VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo));
|
||||
|
||||
// Prepare for transfer
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -265,7 +265,7 @@ public:
|
|||
);
|
||||
|
||||
// Prepare for shader read
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
imageMemoryBarrier.subresourceRange = subresourceRange;
|
||||
|
||||
// Only sets masks for layouts used in this example
|
||||
// For a more complete version that can be used with other layouts see vkTools::setImageLayout
|
||||
// For a more complete version that can be used with other layouts see vks::tools::setImageLayout
|
||||
|
||||
// Source layouts (old)
|
||||
switch (oldImageLayout)
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ public:
|
|||
|
||||
// Optimal image will be used as destination for the copy, so we must transfer from our
|
||||
// initial undefined image layout to the transfer destination layout
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
texture.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -427,7 +427,7 @@ public:
|
|||
|
||||
// Change texture image layout to shader read after all mip levels have been copied
|
||||
texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
texture.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ public:
|
|||
subresourceRange.levelCount = 1;
|
||||
subresourceRange.layerCount = layerCount;
|
||||
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
textureArray.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -270,7 +270,7 @@ public:
|
|||
|
||||
// Change texture image layout to shader read after all faces have been copied
|
||||
textureArray.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
textureArray.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ public:
|
|||
subresourceRange.levelCount = cubeMap.mipLevels;
|
||||
subresourceRange.layerCount = 6;
|
||||
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
cubeMap.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -249,7 +249,7 @@ public:
|
|||
|
||||
// Change texture image layout to shader read after all faces have been copied
|
||||
cubeMap.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
cubeMap.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ public:
|
|||
subresourceRange.layerCount = 1;
|
||||
|
||||
// Optimal image will be used as destination for the copy, so we must transfer from our initial undefined image layout to the transfer destination layout
|
||||
vkTools::setImageLayout(copyCmd, texture.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange);
|
||||
vks::tools::setImageLayout(copyCmd, texture.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange);
|
||||
|
||||
// Copy the first mip of the chain, remaining mips will be generated
|
||||
VkBufferImageCopy bufferCopyRegion = {};
|
||||
|
|
@ -217,7 +217,7 @@ public:
|
|||
|
||||
// Transition first mip level to transfer source for read during blit
|
||||
texture.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
copyCmd,
|
||||
texture.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -265,7 +265,7 @@ public:
|
|||
mipSubRange.layerCount = 1;
|
||||
|
||||
// Transiton current mip level to transfer dest
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
blitCmd,
|
||||
texture.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -287,7 +287,7 @@ public:
|
|||
VK_FILTER_LINEAR);
|
||||
|
||||
// Transiton current mip level to transfer source for read in next iteration
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
blitCmd,
|
||||
texture.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
@ -300,7 +300,7 @@ public:
|
|||
|
||||
// After the loop, all mip layers are in TRANSFER_SRC layout, so transition all to SHADER_READ
|
||||
subresourceRange.levelCount = texture.mipLevels;
|
||||
vkTools::setImageLayout(
|
||||
vks::tools::setImageLayout(
|
||||
blitCmd,
|
||||
texture.image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
|
|
|
|||
|
|
@ -905,7 +905,7 @@ public:
|
|||
// Check if the GPU supports sparse residency for 2D images
|
||||
if (!vulkanDevice->features.sparseResidencyImage2D)
|
||||
{
|
||||
vkTools::exitFatal("Device does not support sparse residency for 2D images!", "Feature not supported");
|
||||
vks::tools::exitFatal("Device does not support sparse residency for 2D images!", "Feature not supported");
|
||||
}
|
||||
loadAssets();
|
||||
generateTerrain();
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Base", "Base", "{09B9A54B-F
|
|||
base\vulkanswapchain.hpp = base\vulkanswapchain.hpp
|
||||
base\vulkantextoverlay.hpp = base\vulkantextoverlay.hpp
|
||||
base\VulkanTexture.hpp = base\VulkanTexture.hpp
|
||||
base\vulkantools.cpp = base\vulkantools.cpp
|
||||
base\vulkantools.h = base\vulkantools.h
|
||||
base\VulkanTools.h = base\VulkanTools.h
|
||||
base\VulkanTools.hpp = base\VulkanTools.hpp
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "indirectdraw", "indirectdraw\indirectdraw.vcxproj", "{2BBDD10F-2C9D-4BEA-8C7B-1C510A2CE08B}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue