Introduce usage of clang-format to format vulkan.hpp and the other sources.

This commit is contained in:
asuessenbach 2020-04-12 21:49:12 +02:00
parent ce9fd81bd9
commit f5e59484a6
68 changed files with 56064 additions and 35586 deletions

89
.clang-format Normal file
View File

@ -0,0 +1,89 @@
---
AccessModifierOffset : -2
AlignAfterOpenBracket : Align
AlignConsecutiveAssignments : true
AlignConsecutiveDeclarations : true
AlignConsecutiveMacros : true
AlignEscapedNewlines : Left
AlignOperands : true
AlignTrailingComments : true
AllowAllArgumentsOnNextLine : true
AllowAllConstructorInitializersOnNextLine : true
AllowAllParametersOfDeclarationOnNextLine : true
AllowShortBlocksOnASingleLine : Empty
AllowShortCaseLabelsOnASingleLine : true
AllowShortFunctionsOnASingleLine : Empty
AllowShortIfStatementsOnASingleLine : Never
AllowShortLambdasOnASingleLine : Inline
AllowShortLoopsOnASingleLine : false
AlwaysBreakAfterReturnType : None
AlwaysBreakBeforeMultilineStrings : true
AlwaysBreakTemplateDeclarations : Yes
BinPackArguments : false
BinPackParameters : false
BraceWrapping :
AfterCaseLabel : true
AfterClass : true
AfterControlStatement : Always
AfterEnum : true
AfterFunction : true
AfterNamespace : true
AfterStruct : true
AfterUnion : true
AfterExternBlock : true
BeforeCatch : true
BeforeElse : true
# BeforeLambdaBody : true
IndentBraces : false
SplitEmptyFunction : false
SplitEmptyRecord : false
SplitEmptyNamespace : false
BreakBeforeBinaryOperators : None
BreakBeforeBraces : Custom
BreakBeforeTernaryOperators : true
BreakConstructorInitializers : BeforeColon
BreakInheritanceList : BeforeComma
BreakStringLiterals : false
ColumnLimit : 120
CompactNamespaces : false
ConstructorInitializerAllOnOneLineOrOnePerLine : true
ConstructorInitializerIndentWidth : 2
ContinuationIndentWidth : 2
Cpp11BracedListStyle : false
FixNamespaceComments : true
IncludeBlocks : Regroup
# IndentCaseBlocks : true
IndentCaseLabels : true
IndentPPDirectives : AfterHash
IndentWidth : 2
IndentWrappedFunctionNames : true
KeepEmptyLinesAtTheStartOfBlocks : false
MaxEmptyLinesToKeep : 1
NamespaceIndentation : All
PointerAlignment : Middle
ReflowComments : true
SortIncludes : true
SortUsingDeclarations : true
SpaceAfterCStyleCast : false
SpaceAfterLogicalNot : false
SpaceAfterTemplateKeyword : true
SpaceBeforeAssignmentOperators : true
SpaceBeforeCpp11BracedList : false
SpaceBeforeCtorInitializerColon : true
SpaceBeforeInheritanceColon : true
SpaceBeforeParens : ControlStatements
SpaceBeforeRangeBasedForLoopColon : true
SpaceBeforeSquareBrackets : false
SpaceInEmptyBlock : false
SpaceInEmptyParentheses : false
SpacesBeforeTrailingComments : 2
SpacesInAngles : false
SpacesInCStyleCastParentheses : false
# SpacesInConditionalStatement : true
SpacesInContainerLiterals : true
SpacesInParentheses : true
SpacesInSquareBrackets : false
Standard : Latest
UseCRLF : true
UseTab : Never
...

View File

@ -30,6 +30,14 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
project(VulkanHppGenerator) project(VulkanHppGenerator)
find_program(CLANG_FORMAT_EXECUTABLE NAMES clang-format)
if(CLANG_FORMAT_EXECUTABLE)
add_definitions(-DCLANG_FORMAT_EXECUTABLE="${CLANG_FORMAT_EXECUTABLE}")
else()
message(WARNGING " Could not find clang-format. Generated vulkan.hpp will not be nicely formatted.")
endif()
if(MSVC) if(MSVC)
add_compile_options(/W4) add_compile_options(/W4)
else(MSVC) else(MSVC)

View File

@ -17,6 +17,12 @@ Vulkan-Hpp requires a C++11 capable compiler to compile. The following compilers
* GCC >= 4.8.2 (earlier version might work, but are untested) * GCC >= 4.8.2 (earlier version might work, but are untested)
* Clang >= 3.3 * Clang >= 3.3
### Optional Features
#### Formatting
If the program clang-format is found by CMake, the define CLANG_FORMAT_EXECUTABLE is set accordingly. In that case, the generated vulkan.hpp is formatted using the .clang-format file located in the root directory of this project. Otherwise it's formatted as hard-coded in the generator.
## Usage ## Usage
### namespace vk ### namespace vk

File diff suppressed because it is too large Load Diff

View File

@ -14,342 +14,566 @@
#pragma once #pragma once
#include <map>
#include <iostream> #include <iostream>
#include <map>
#include <set> #include <set>
#include <vector>
#include <tinyxml2.h> #include <tinyxml2.h>
#include <vector>
class VulkanHppGenerator class VulkanHppGenerator
{ {
public: public:
VulkanHppGenerator(tinyxml2::XMLDocument const& document); VulkanHppGenerator( tinyxml2::XMLDocument const & document );
void appendBaseTypes(std::string & str) const; void appendBaseTypes( std::string & str ) const;
void appendBitmasks(std::string & str) const; void appendBitmasks( std::string & str ) const;
void appendDispatchLoaderDynamic(std::string & str); // use vkGet*ProcAddress to get function pointers void appendDispatchLoaderDynamic( std::string & str ); // use vkGet*ProcAddress to get function pointers
void appendDispatchLoaderStatic(std::string & str); // use exported symbols from loader void appendDispatchLoaderStatic( std::string & str ); // use exported symbols from loader
void appendDispatchLoaderDefault(std::string & str); // typedef to DispatchLoaderStatic or undefined type, based on VK_NO_PROTOTYPES void appendDispatchLoaderDefault(
void appendEnums(std::string & str) const; std::string & str ); // typedef to DispatchLoaderStatic or undefined type, based on VK_NO_PROTOTYPES
void appendForwardDeclarations(std::string & str) const; void appendEnums( std::string & str ) const;
void appendHandles(std::string & str) const; void appendForwardDeclarations( std::string & str ) const;
void appendHandlesCommandDefintions(std::string & str) const; void appendHandles( std::string & str ) const;
void appendHashStructures(std::string& str) const; void appendHandlesCommandDefintions( std::string & str ) const;
void appendResultExceptions(std::string & str) const; void appendHashStructures( std::string & str ) const;
void appendStructs(std::string & str) const; void appendResultExceptions( std::string & str ) const;
void appendStructureChainValidation(std::string & str); void appendStructs( std::string & str ) const;
void appendThrowExceptions(std::string & str) const; void appendStructureChainValidation( std::string & str );
std::string const& getTypesafeCheck() const; void appendThrowExceptions( std::string & str ) const;
std::string const& getVersion() const; std::string const & getTypesafeCheck() const;
std::string const& getVulkanLicenseHeader() const; std::string const & getVersion() const;
std::string const & getVulkanLicenseHeader() const;
private: private:
struct BaseTypeData struct BaseTypeData
{
BaseTypeData( std::string const & type_, int line ) : type( type_ ), xmlLine( line ) {}
std::string type;
int xmlLine;
};
struct BitmaskData
{
BitmaskData( std::string const & r, std::string const & t, int line )
: requirements( r ), type( t ), xmlLine( line )
{}
std::string requirements;
std::string type;
std::string platform;
std::string alias;
int xmlLine;
};
struct NameData
{
std::string name;
std::vector<std::string> arraySizes;
std::string bitCount;
};
struct TypeData
{
std::string compose() const;
bool operator==( TypeData const & rhs ) const
{ {
BaseTypeData(std::string const& type_, int line) return ( prefix == rhs.prefix ) && ( type == rhs.type ) && ( postfix == rhs.postfix );
: type(type_) }
, xmlLine(line)
{}
std::string type; std::string prefix;
int xmlLine; std::string type;
}; std::string postfix;
};
struct BitmaskData struct ParamData
{ {
BitmaskData(std::string const& r, std::string const& t, int line) ParamData( int line ) : optional( false ), xmlLine( line ) {}
: requirements(r)
, type(t)
, xmlLine(line)
{}
std::string requirements; TypeData type;
std::string type; std::string name;
std::string platform; std::vector<std::string> arraySizes;
std::string alias; std::string len;
int xmlLine; bool optional;
}; int xmlLine;
};
struct NameData struct CommandData
{ {
std::string name; CommandData( int line ) : xmlLine( line ) {}
std::vector<std::string> arraySizes;
std::string bitCount;
};
struct TypeData std::vector<ParamData> params;
{ std::string platform;
std::string compose() const; std::string returnType;
std::vector<std::string> successCodes;
std::vector<std::string> errorCodes;
std::set<std::string> aliases;
int xmlLine;
};
bool operator==(TypeData const& rhs) const struct EnumValueData
{ {
return (prefix == rhs.prefix) && (type == rhs.type) && (postfix == rhs.postfix); EnumValueData( std::string const & vulkan, std::string const & vk, bool singleBit_ )
} : vulkanValue( vulkan ), vkValue( vk ), singleBit( singleBit_ )
{}
std::string prefix; std::string vulkanValue;
std::string type; std::string vkValue;
std::string postfix; bool singleBit;
}; };
struct ParamData struct EnumData
{ {
ParamData(int line) void addEnumValue( int line,
: optional(false) std::string const & valueName,
, xmlLine(line) bool bitmask,
{} bool bitpos,
std::string const & prefix,
std::string const & postfix,
std::string const & tag );
TypeData type; std::string alias; // alias for this enum
std::string name; std::vector<std::pair<std::string, std::string>>
std::vector<std::string> arraySizes; aliases; // pairs of vulkan enum value and corresponding vk::-namespace enum value
std::string len; bool isBitmask = false;
bool optional; std::string platform;
int xmlLine; std::vector<EnumValueData> values;
}; };
struct CommandData struct ExtensionData
{ {
CommandData(int line) ExtensionData( int line ) : xmlLine( line ) {}
: xmlLine(line)
{}
std::vector<ParamData> params; std::string deprecatedBy;
std::string platform; std::string obsoletedBy;
std::string returnType; std::string promotedTo;
std::vector<std::string> successCodes; std::map<std::string, int> requirements;
std::vector<std::string> errorCodes; int xmlLine;
std::set<std::string> aliases; };
int xmlLine;
};
struct EnumValueData struct FuncPointerData
{ {
EnumValueData(std::string const& vulkan, std::string const& vk, bool singleBit_) FuncPointerData( std::string const & r, int line ) : requirements( r ), xmlLine( line ) {}
: vulkanValue(vulkan)
, vkValue(vk)
, singleBit(singleBit_)
{}
std::string vulkanValue; std::string requirements;
std::string vkValue; int xmlLine;
bool singleBit; };
};
struct EnumData struct HandleData
{ {
void addEnumValue(int line, std::string const& valueName, bool bitmask, bool bitpos, std::string const& prefix, std::string const& postfix, std::string const& tag); HandleData( std::vector<std::string> const & p, int line ) : parents( p ), xmlLine( line ) {}
std::string alias; // alias for this enum std::string alias;
std::vector<std::pair<std::string, std::string>> aliases; // pairs of vulkan enum value and corresponding vk::-namespace enum value std::set<std::string> childrenHandles;
bool isBitmask = false; std::map<std::string, CommandData> commands;
std::string platform; std::string deleteCommand;
std::vector<EnumValueData> values; std::string deletePool;
}; std::string platform;
std::vector<std::string> parents;
int xmlLine;
};
struct ExtensionData struct MemberData
{ {
ExtensionData(int line) MemberData( int line ) : xmlLine( line ) {}
: xmlLine(line)
{}
std::string deprecatedBy; TypeData type;
std::string obsoletedBy; std::string name;
std::string promotedTo; std::vector<std::string> arraySizes;
std::map<std::string, int> requirements; std::string bitCount;
int xmlLine; std::string values;
}; std::string usedConstant;
int xmlLine;
};
struct FuncPointerData struct StructureData
{ {
FuncPointerData(std::string const& r, int line) StructureData( std::vector<std::string> const & extends, int line )
: requirements(r) : returnedOnly( false ), isUnion( false ), structExtends( extends ), xmlLine( line )
, xmlLine(line) {}
{}
std::string requirements; bool returnedOnly;
int xmlLine; bool isUnion;
}; std::vector<MemberData> members;
std::string platform;
std::vector<std::string> structExtends;
std::set<std::string> aliases;
std::string subStruct;
int xmlLine;
};
struct HandleData enum class TypeCategory
{ {
HandleData(std::vector<std::string> const& p, int line) Bitmask,
: parents(p) BaseType,
, xmlLine(line) Define,
{} Enum,
FuncPointer,
Handle,
Requires,
Struct,
Union,
Unknown
};
std::string alias; private:
std::set<std::string> childrenHandles; void appendArgumentPlainType( std::string & str, ParamData const & paramData ) const;
std::map<std::string, CommandData> commands; void appendArguments( std::string & str,
std::string deleteCommand; CommandData const & commandData,
std::string deletePool; size_t returnParamIndex,
std::string platform; size_t templateParamIndex,
std::vector<std::string> parents; std::map<size_t, size_t> const & vectorParamIndices,
int xmlLine; bool twoStep,
}; bool firstCall,
bool singular,
struct MemberData size_t from,
{ size_t to ) const;
MemberData(int line) void appendArgumentVector( std::string & str,
: xmlLine(line) size_t paramIndex,
{} ParamData const & paramData,
size_t returnParamIndex,
TypeData type; size_t templateParamIndex,
std::string name; bool twoStep,
std::vector<std::string> arraySizes; bool firstCall,
std::string bitCount; bool singular ) const;
std::string values; void appendArgumentVulkanType( std::string & str, ParamData const & paramData ) const;
std::string usedConstant; void appendBitmask( std::string & os,
int xmlLine; std::string const & bitmaskName,
}; std::string const & bitmaskType,
std::string const & bitmaskAlias,
struct StructureData std::string const & enumName,
{ std::vector<EnumValueData> const & enumValues ) const;
StructureData(std::vector<std::string> const& extends, int line) void appendBitmaskToStringFunction( std::string & str,
: returnedOnly(false) std::string const & flagsName,
, isUnion(false) std::string const & enumName,
, structExtends(extends) std::vector<EnumValueData> const & enumValues ) const;
, xmlLine(line) void appendCall( std::string & str,
{} std::string const & name,
CommandData const & commandData,
bool returnedOnly; size_t returnParamIndex,
bool isUnion; size_t templateParamIndex,
std::vector<MemberData> members; std::map<size_t, size_t> const & vectorParamIndices,
std::string platform; bool twoStep,
std::vector<std::string> structExtends; bool firstCall,
std::set<std::string> aliases; bool singular ) const;
std::string subStruct; void appendCommand( std::string & str,
int xmlLine; std::string const & indentation,
}; std::string const & name,
CommandData const & commandData,
enum class TypeCategory bool definition ) const;
{ void appendEnum( std::string & str, std::pair<std::string, EnumData> const & enumData ) const;
Bitmask, void appendEnumInitializer( std::string & str,
BaseType, TypeData const & type,
Define, std::vector<std::string> const & arraySizes,
Enum, std::vector<EnumValueData> const & values,
FuncPointer, bool argument ) const;
Handle, void appendEnumToString( std::string & str, std::pair<std::string, EnumData> const & enumData ) const;
Requires, void appendFunction( std::string & str,
Struct, std::string const & indentation,
Union, std::string const & name,
Unknown CommandData const & commandData,
}; size_t returnParamIndex,
size_t templateParamIndex,
private: std::map<size_t, size_t> const & vectorParamIndices,
void appendArgumentPlainType(std::string & str, ParamData const& paramData) const; bool twoStep,
void appendArguments(std::string & str, CommandData const& commandData, size_t returnParamIndex, size_t templateParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool twoStep, bool firstCall, bool singular, size_t from, size_t to) const; std::string const & enhancedReturnType,
void appendArgumentVector(std::string & str, size_t paramIndex, ParamData const& paramData, size_t returnParamIndex, size_t templateParamIndex, bool twoStep, bool firstCall, bool singular) const; bool definition,
void appendArgumentVulkanType(std::string & str, ParamData const& paramData) const; bool enhanced,
void appendBitmask(std::string & os, std::string const& bitmaskName, std::string const& bitmaskType, std::string const& bitmaskAlias, std::string const& enumName, std::vector<EnumValueData> const& enumValues) const; bool singular,
void appendBitmaskToStringFunction(std::string & str, std::string const& flagsName, std::string const& enumName, std::vector<EnumValueData> const& enumValues) const; bool unique,
void appendCall(std::string &str, std::string const& name, CommandData const& commandData, size_t returnParamIndex, size_t templateParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool twoStep, bool firstCall, bool singular) const; bool isStructureChain,
void appendCommand(std::string & str, std::string const& indentation, std::string const& name, CommandData const& commandData, bool definition) const; bool withAllocator ) const;
void appendEnum(std::string & str, std::pair<std::string, EnumData> const& enumData) const; void appendFunctionBodyEnhanced( std::string & str,
void appendEnumInitializer(std::string& str, TypeData const& type, std::vector<std::string> const& arraySizes, std::vector<EnumValueData> const& values, bool argument) const; std::string const & indentation,
void appendEnumToString(std::string & str, std::pair<std::string, EnumData> const& enumData) const; std::string const & name,
void appendFunction(std::string & str, std::string const& indentation, std::string const& name, CommandData const& commandData, size_t returnParamIndex, size_t templateParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool twoStep, std::string const& enhancedReturnType, bool definition, bool enhanced, bool singular, bool unique, bool isStructureChain, bool withAllocator) const; CommandData const & commandData,
void appendFunctionBodyEnhanced(std::string & str, std::string const& indentation, std::string const& name, CommandData const& commandData, size_t returnParamIndex, size_t templateParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool twoStep, std::string const& enhancedReturnType, bool singular, bool unique, bool isStructureChain, bool withAllocator) const; size_t returnParamIndex,
std::string appendFunctionBodyEnhancedLocalReturnVariable(std::string & str, std::string const& indentation, CommandData const& commandData, size_t returnParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool twoStep, std::string const& enhancedReturnType, bool singular, bool isStructureChain, bool withAllocator) const; size_t templateParamIndex,
void appendFunctionBodyEnhancedLocalReturnVariableVectorSize(std::string & str, std::vector<ParamData> const& params, std::pair<size_t, size_t> const& vectorParamIndex, size_t returnParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool withAllocator) const; std::map<size_t, size_t> const & vectorParamIndices,
void appendFunctionBodyEnhancedMultiVectorSizeCheck(std::string & str, std::string const& indentation, std::string const& name, CommandData const& commandData, size_t returnParamIndex, std::map<size_t, size_t> const& vectorParamIndices) const; bool twoStep,
void appendFunctionBodyEnhancedReturnResultValue(std::string & str, std::string const& indentation, std::string const& returnName, std::string const& name, CommandData const& commandData, size_t returnParamIndex, bool twoStep, bool singular, bool unique) const; std::string const & enhancedReturnType,
void appendFunctionBodyEnhancedSingleStep(std::string & str, std::string const& indentation, std::string const& name, CommandData const& commandData, size_t returnParamIndex, size_t templateParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool singular) const; bool singular,
void appendFunctionBodyEnhancedTwoStep(std::string & str, std::string const& indentation, std::string const& name, CommandData const& commandData, size_t returnParamIndex, size_t templateParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool singular, std::string const& returnName) const; bool unique,
void appendFunctionBodyEnhancedVectorOfStructureChain(std::string & str, std::string const& indentation, std::string const& name, CommandData const& commandData, size_t returnParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool withAllocator) const; bool isStructureChain,
void appendFunctionBodyEnhancedVectorOfUniqueHandles(std::string & str, std::string const& indentation, std::string const& name, CommandData const& commandData, size_t returnParamIndex, size_t templateParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool twoStep, bool singular, bool withAllocator) const; bool withAllocator ) const;
void appendFunctionBodyStandard(std::string & str, std::string const& indentation, std::string const& commandName, CommandData const& commandData) const; std::string appendFunctionBodyEnhancedLocalReturnVariable( std::string & str,
void appendFunctionBodyStandardArgument(std::string & str, TypeData const& typeData, std::string const& name, std::vector<std::string> const& arraySizes) const; std::string const & indentation,
bool appendFunctionHeaderArgumentEnhanced(std::string & str, ParamData const& param, size_t paramIndex, std::map<size_t, size_t> const& vectorParamIndices, bool skip, bool argEncountered, bool isTemplateParam, bool isLastArgument, bool singular, bool withDefaults, bool withAllocator) const; CommandData const & commandData,
void appendFunctionHeaderArgumentEnhancedPointer(std::string & str, ParamData const& param, std::string const& strippedParameterName, bool withDefaults, bool withAllocator) const; size_t returnParamIndex,
void appendFunctionHeaderArgumentEnhancedSimple(std::string & str, ParamData const& param, bool lastArgument, bool withDefaults, bool withAllocator) const; std::map<size_t, size_t> const & vectorParamIndices,
void appendFunctionHeaderArgumentEnhancedVector(std::string & str, ParamData const& param, std::string const& strippedParameterName, bool hasSizeParam, bool isTemplateParam, bool singular, bool withDefaults, bool withAllocator) const; bool twoStep,
void appendFunctionHeaderArguments(std::string & str, std::string const& name, CommandData const& commandData, size_t returnParamIndex, size_t templateParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool enhanced, bool singular, bool withDefaults, bool withAllocator) const; std::string const & enhancedReturnType,
void appendFunctionHeaderArgumentsEnhanced(std::string & str, std::string const& name, CommandData const& commandData, size_t returnParamIndex, size_t templateParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool singular, bool withDefaults, bool withAllocator) const; bool singular,
void appendFunctionHeaderArgumentsStandard(std::string & str, std::string const& name, CommandData const& commandData, bool withDefaults) const; bool isStructureChain,
bool appendFunctionHeaderArgumentStandard(std::string & str, ParamData const& param, bool argEncountered, bool isLastArgument, bool withDefaults) const; bool withAllocator ) const;
void appendFunctionHeaderReturnType(std::string & str, CommandData const& commandData, size_t returnParamIndex, std::map<size_t, size_t> const& vectorParamIndices, std::string const& enhancedReturnType, bool enhanced, bool twoStep, bool singular, bool unique, bool isStructureChain) const; void appendFunctionBodyEnhancedLocalReturnVariableVectorSize( std::string & str,
void appendFunctionHeaderTemplate(std::string & str, std::string const& indentation, size_t returnParamIndex, size_t templateParamIndex, std::string const& enhancedReturnType, bool enhanced, bool singular, bool unique, bool withDefault, bool isStructureChain) const; std::vector<ParamData> const & params,
void appendHandle(std::string & str, std::pair<std::string, HandleData> const& handle, std::set<std::string> & listedHandles) const; std::pair<size_t, size_t> const & vectorParamIndex,
void appendPlatformEnter(std::string & str, bool isAliased, std::string const& platform) const; size_t returnParamIndex,
void appendPlatformLeave(std::string & str, bool isAliased, std::string const& platform) const; std::map<size_t, size_t> const & vectorParamIndices,
void appendStruct(std::string & str, std::pair<std::string, StructureData> const& structure, std::set<std::string> & listedStructures) const; bool withAllocator ) const;
void appendStructAssignmentOperator(std::string &str, std::pair<std::string, StructureData> const& structure, std::string const& prefix) const; void appendFunctionBodyEnhancedMultiVectorSizeCheck( std::string & str,
void appendStructCompareOperators(std::string & str, std::pair<std::string, StructureData> const& structure) const; std::string const & indentation,
void appendStructConstructor(std::string &str, std::pair<std::string, StructureData> const& structData, std::string const& prefix) const; std::string const & name,
bool appendStructConstructorArgument(std::string & str, bool listedArgument, std::string const& indentation, MemberData const& memberData) const; CommandData const & commandData,
void appendStructCopyConstructors(std::string & str, std::string const& vkName) const; size_t returnParamIndex,
void appendStructMembers(std::string & str, std::pair<std::string,StructureData> const& structData, std::string const& prefix) const; std::map<size_t, size_t> const & vectorParamIndices ) const;
void appendStructSetter(std::string & str, std::string const& structureName, bool isUnion, MemberData const& memberData) const; void appendFunctionBodyEnhancedReturnResultValue( std::string & str,
void appendStructSubConstructor(std::string &str, std::pair<std::string, StructureData> const& structData, std::string const& prefix) const; std::string const & indentation,
void appendStructure(std::string & str, std::pair<std::string, StructureData> const& structure) const; std::string const & returnName,
void appendUnion(std::string & str, std::pair<std::string, StructureData> const& structure) const; std::string const & name,
void appendUniqueTypes(std::string &str, std::string const& parentType, std::set<std::string> const& childrenTypes) const; CommandData const & commandData,
std::string constructConstexprString(std::pair<std::string, StructureData> const& structData) const; size_t returnParamIndex,
void checkCorrectness(); bool twoStep,
bool checkLenAttribute(std::string const& len, std::vector<ParamData> const& params); bool singular,
bool containsArray(std::string const& type) const; bool unique ) const;
bool containsUnion(std::string const& type) const; void appendFunctionBodyEnhancedSingleStep( std::string & str,
std::string determineEnhancedReturnType(CommandData const& commandData, size_t returnParamIndex, std::map<size_t, size_t> const& vectorParamIndices, bool isStructureChain) const; std::string const & indentation,
size_t determineReturnParamIndex(CommandData const& commandData, std::map<size_t, size_t> const& vectorParamIndices, bool twoStep) const; std::string const & name,
std::string determineSubStruct(std::pair<std::string, StructureData> const& structure) const; CommandData const & commandData,
size_t determineTemplateParamIndex(std::vector<ParamData> const& params, std::map<size_t, size_t> const& vectorParamIndices) const; size_t returnParamIndex,
std::map<size_t, size_t> determineVectorParamIndices(std::vector<ParamData> const& params) const; size_t templateParamIndex,
bool holdsSType(std::string const& type) const; std::map<size_t, size_t> const & vectorParamIndices,
bool isTwoStepAlgorithm(std::vector<ParamData> const& params) const; bool singular ) const;
void linkCommandToHandle(int line, std::string const& name, CommandData const& commandData); void appendFunctionBodyEnhancedTwoStep( std::string & str,
void readBaseType(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); std::string const & indentation,
void readBitmask(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); std::string const & name,
void readBitmaskAlias(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); CommandData const & commandData,
void readCommand(tinyxml2::XMLElement const* element); size_t returnParamIndex,
void readCommand(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributess); size_t templateParamIndex,
void readCommandAlias(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); std::map<size_t, size_t> const & vectorParamIndices,
ParamData readCommandParam(tinyxml2::XMLElement const* element, std::vector<ParamData> const& params); bool singular,
std::pair<std::string, std::string> readCommandProto(tinyxml2::XMLElement const* element); std::string const & returnName ) const;
void readCommands(tinyxml2::XMLElement const* element); void appendFunctionBodyEnhancedVectorOfStructureChain( std::string & str,
std::string readComment(tinyxml2::XMLElement const* element); std::string const & indentation,
void readDefine(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); std::string const & name,
void readEnum(tinyxml2::XMLElement const* element, EnumData & enumData, bool bitmask, std::string const& prefix, std::string const& postfix); CommandData const & commandData,
void readEnum(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes, EnumData & enumData, bool bitmask, std::string const& prefix, std::string const& postfix); size_t returnParamIndex,
void readEnumAlias(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes, EnumData & enumData, bool bitmask, std::string const& prefix, std::string const& postfix); std::map<size_t, size_t> const & vectorParamIndices,
void readEnumConstant(tinyxml2::XMLElement const* element); bool withAllocator ) const;
void readEnums(tinyxml2::XMLElement const* element); void appendFunctionBodyEnhancedVectorOfUniqueHandles( std::string & str,
void readExtension(tinyxml2::XMLElement const* element); std::string const & indentation,
void readExtensionDisabledCommand(tinyxml2::XMLElement const* element); std::string const & name,
void readExtensionDisabledEnum(std::string const& extensionName, tinyxml2::XMLElement const* element); CommandData const & commandData,
void readExtensionDisabledRequire(std::string const& extensionName, tinyxml2::XMLElement const* element); size_t returnParamIndex,
void readExtensionDisabledType(tinyxml2::XMLElement const* element); size_t templateParamIndex,
void readExtensionRequire(tinyxml2::XMLElement const* element, std::string const& platform, std::string const& tag, std::map<std::string, int> & requirements); std::map<size_t, size_t> const & vectorParamIndices,
void readExtensionRequireCommand(tinyxml2::XMLElement const* element, std::string const& platform); bool twoStep,
void readExtensionRequireType(tinyxml2::XMLElement const* element, std::string const& platform); bool singular,
void readExtensions(tinyxml2::XMLElement const* element); bool withAllocator ) const;
void readFeature(tinyxml2::XMLElement const* element); void appendFunctionBodyStandard( std::string & str,
void readFeatureRequire(tinyxml2::XMLElement const* element); std::string const & indentation,
void readFuncpointer(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); std::string const & commandName,
void readHandle(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); CommandData const & commandData ) const;
std::pair<NameData, TypeData> readNameAndType(tinyxml2::XMLElement const* elements); void appendFunctionBodyStandardArgument( std::string & str,
void readPlatform(tinyxml2::XMLElement const* element); TypeData const & typeData,
void readPlatforms(tinyxml2::XMLElement const* element); std::string const & name,
void readRegistry(tinyxml2::XMLElement const* element); std::vector<std::string> const & arraySizes ) const;
void readRequireCommand(tinyxml2::XMLElement const* element); bool appendFunctionHeaderArgumentEnhanced( std::string & str,
void readRequireEnum(tinyxml2::XMLElement const* element, std::string const& tag); ParamData const & param,
void readRequireEnum(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes, std::string const& tag); size_t paramIndex,
void readRequireEnumAlias(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes, std::string const& tag); std::map<size_t, size_t> const & vectorParamIndices,
void readRequires(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); bool skip,
void readRequireType(tinyxml2::XMLElement const* element); bool argEncountered,
void readStruct(tinyxml2::XMLElement const* element, bool isUnion, std::map<std::string, std::string> const& attributes); bool isTemplateParam,
void readStructAlias(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); bool isLastArgument,
void readStructMember(tinyxml2::XMLElement const* element, std::vector<MemberData> & members); bool singular,
void readStructMemberEnum(tinyxml2::XMLElement const* element, MemberData & memberData); bool withDefaults,
void readStructMemberName(tinyxml2::XMLElement const* element, MemberData & memberData, std::vector<MemberData> const& members); bool withAllocator ) const;
void readStructMemberType(tinyxml2::XMLElement const* element, MemberData & memberData); void appendFunctionHeaderArgumentEnhancedPointer( std::string & str,
void readTag(tinyxml2::XMLElement const* element); ParamData const & param,
void readTags(tinyxml2::XMLElement const* element); std::string const & strippedParameterName,
void readType(tinyxml2::XMLElement const* element); bool withDefaults,
void readTypeEnum(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); bool withAllocator ) const;
void readTypeInclude(tinyxml2::XMLElement const* element, std::map<std::string, std::string> const& attributes); void appendFunctionHeaderArgumentEnhancedSimple(
void readTypes(tinyxml2::XMLElement const* element); std::string & str, ParamData const & param, bool lastArgument, bool withDefaults, bool withAllocator ) const;
void registerDeleter(std::string const& name, std::pair<std::string, CommandData> const& commandData); void appendFunctionHeaderArgumentEnhancedVector( std::string & str,
void setVulkanLicenseHeader(int line, std::string const& comment); ParamData const & param,
std::string toString(TypeCategory category); std::string const & strippedParameterName,
bool hasSizeParam,
bool isTemplateParam,
bool singular,
bool withDefaults,
bool withAllocator ) const;
void appendFunctionHeaderArguments( std::string & str,
std::string const & name,
CommandData const & commandData,
size_t returnParamIndex,
size_t templateParamIndex,
std::map<size_t, size_t> const & vectorParamIndices,
bool enhanced,
bool singular,
bool withDefaults,
bool withAllocator ) const;
void appendFunctionHeaderArgumentsEnhanced( std::string & str,
std::string const & name,
CommandData const & commandData,
size_t returnParamIndex,
size_t templateParamIndex,
std::map<size_t, size_t> const & vectorParamIndices,
bool singular,
bool withDefaults,
bool withAllocator ) const;
void appendFunctionHeaderArgumentsStandard( std::string & str,
std::string const & name,
CommandData const & commandData,
bool withDefaults ) const;
bool appendFunctionHeaderArgumentStandard(
std::string & str, ParamData const & param, bool argEncountered, bool isLastArgument, bool withDefaults ) const;
void appendFunctionHeaderReturnType( std::string & str,
CommandData const & commandData,
size_t returnParamIndex,
std::map<size_t, size_t> const & vectorParamIndices,
std::string const & enhancedReturnType,
bool enhanced,
bool twoStep,
bool singular,
bool unique,
bool isStructureChain ) const;
void appendFunctionHeaderTemplate( std::string & str,
std::string const & indentation,
size_t returnParamIndex,
size_t templateParamIndex,
std::string const & enhancedReturnType,
bool enhanced,
bool singular,
bool unique,
bool withDefault,
bool isStructureChain ) const;
void appendHandle( std::string & str,
std::pair<std::string, HandleData> const & handle,
std::set<std::string> & listedHandles ) const;
void appendPlatformEnter( std::string & str, bool isAliased, std::string const & platform ) const;
void appendPlatformLeave( std::string & str, bool isAliased, std::string const & platform ) const;
void appendStruct( std::string & str,
std::pair<std::string, StructureData> const & structure,
std::set<std::string> & listedStructures ) const;
void appendStructAssignmentOperator( std::string & str,
std::pair<std::string, StructureData> const & structure,
std::string const & prefix ) const;
void appendStructCompareOperators( std::string & str, std::pair<std::string, StructureData> const & structure ) const;
void appendStructConstructor( std::string & str,
std::pair<std::string, StructureData> const & structData,
std::string const & prefix ) const;
bool appendStructConstructorArgument( std::string & str,
bool listedArgument,
std::string const & indentation,
MemberData const & memberData ) const;
void appendStructCopyConstructors( std::string & str, std::string const & vkName ) const;
void appendStructMembers( std::string & str,
std::pair<std::string, StructureData> const & structData,
std::string const & prefix ) const;
void appendStructSetter( std::string & str,
std::string const & structureName,
bool isUnion,
MemberData const & memberData ) const;
void appendStructSubConstructor( std::string & str,
std::pair<std::string, StructureData> const & structData,
std::string const & prefix ) const;
void appendStructure( std::string & str, std::pair<std::string, StructureData> const & structure ) const;
void appendUnion( std::string & str, std::pair<std::string, StructureData> const & structure ) const;
void appendUniqueTypes( std::string & str,
std::string const & parentType,
std::set<std::string> const & childrenTypes ) const;
std::string constructConstexprString( std::pair<std::string, StructureData> const & structData ) const;
void checkCorrectness();
bool checkLenAttribute( std::string const & len, std::vector<ParamData> const & params );
bool containsArray( std::string const & type ) const;
bool containsUnion( std::string const & type ) const;
std::string determineEnhancedReturnType( CommandData const & commandData,
size_t returnParamIndex,
std::map<size_t, size_t> const & vectorParamIndices,
bool isStructureChain ) const;
size_t determineReturnParamIndex( CommandData const & commandData,
std::map<size_t, size_t> const & vectorParamIndices,
bool twoStep ) const;
std::string determineSubStruct( std::pair<std::string, StructureData> const & structure ) const;
size_t determineTemplateParamIndex( std::vector<ParamData> const & params,
std::map<size_t, size_t> const & vectorParamIndices ) const;
std::map<size_t, size_t> determineVectorParamIndices( std::vector<ParamData> const & params ) const;
bool holdsSType( std::string const & type ) const;
bool isTwoStepAlgorithm( std::vector<ParamData> const & params ) const;
void linkCommandToHandle( int line, std::string const & name, CommandData const & commandData );
void readBaseType( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
void readBitmask( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
void readBitmaskAlias( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
void readCommand( tinyxml2::XMLElement const * element );
void readCommand( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributess );
void readCommandAlias( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
ParamData readCommandParam( tinyxml2::XMLElement const * element, std::vector<ParamData> const & params );
std::pair<std::string, std::string> readCommandProto( tinyxml2::XMLElement const * element );
void readCommands( tinyxml2::XMLElement const * element );
std::string readComment( tinyxml2::XMLElement const * element );
void readDefine( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
void readEnum( tinyxml2::XMLElement const * element,
EnumData & enumData,
bool bitmask,
std::string const & prefix,
std::string const & postfix );
void readEnum( tinyxml2::XMLElement const * element,
std::map<std::string, std::string> const & attributes,
EnumData & enumData,
bool bitmask,
std::string const & prefix,
std::string const & postfix );
void readEnumAlias( tinyxml2::XMLElement const * element,
std::map<std::string, std::string> const & attributes,
EnumData & enumData,
bool bitmask,
std::string const & prefix,
std::string const & postfix );
void readEnumConstant( tinyxml2::XMLElement const * element );
void readEnums( tinyxml2::XMLElement const * element );
void readExtension( tinyxml2::XMLElement const * element );
void readExtensionDisabledCommand( tinyxml2::XMLElement const * element );
void readExtensionDisabledEnum( std::string const & extensionName, tinyxml2::XMLElement const * element );
void readExtensionDisabledRequire( std::string const & extensionName, tinyxml2::XMLElement const * element );
void readExtensionDisabledType( tinyxml2::XMLElement const * element );
void readExtensionRequire( tinyxml2::XMLElement const * element,
std::string const & platform,
std::string const & tag,
std::map<std::string, int> & requirements );
void readExtensionRequireCommand( tinyxml2::XMLElement const * element, std::string const & platform );
void readExtensionRequireType( tinyxml2::XMLElement const * element, std::string const & platform );
void readExtensions( tinyxml2::XMLElement const * element );
void readFeature( tinyxml2::XMLElement const * element );
void readFeatureRequire( tinyxml2::XMLElement const * element );
void readFuncpointer( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
void readHandle( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
std::pair<NameData, TypeData> readNameAndType( tinyxml2::XMLElement const * elements );
void readPlatform( tinyxml2::XMLElement const * element );
void readPlatforms( tinyxml2::XMLElement const * element );
void readRegistry( tinyxml2::XMLElement const * element );
void readRequireCommand( tinyxml2::XMLElement const * element );
void readRequireEnum( tinyxml2::XMLElement const * element, std::string const & tag );
void readRequireEnum( tinyxml2::XMLElement const * element,
std::map<std::string, std::string> const & attributes,
std::string const & tag );
void readRequireEnumAlias( tinyxml2::XMLElement const * element,
std::map<std::string, std::string> const & attributes,
std::string const & tag );
void readRequires( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
void readRequireType( tinyxml2::XMLElement const * element );
void readStruct( tinyxml2::XMLElement const * element,
bool isUnion,
std::map<std::string, std::string> const & attributes );
void readStructAlias( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
void readStructMember( tinyxml2::XMLElement const * element, std::vector<MemberData> & members );
void readStructMemberEnum( tinyxml2::XMLElement const * element, MemberData & memberData );
void readStructMemberName( tinyxml2::XMLElement const * element,
MemberData & memberData,
std::vector<MemberData> const & members );
void readStructMemberType( tinyxml2::XMLElement const * element, MemberData & memberData );
void readTag( tinyxml2::XMLElement const * element );
void readTags( tinyxml2::XMLElement const * element );
void readType( tinyxml2::XMLElement const * element );
void readTypeEnum( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
void readTypeInclude( tinyxml2::XMLElement const * element, std::map<std::string, std::string> const & attributes );
void readTypes( tinyxml2::XMLElement const * element );
void registerDeleter( std::string const & name, std::pair<std::string, CommandData> const & commandData );
void setVulkanLicenseHeader( int line, std::string const & comment );
std::string toString( TypeCategory category );
private: private:
std::map<std::string, BaseTypeData> m_baseTypes; std::map<std::string, BaseTypeData> m_baseTypes;

View File

@ -16,38 +16,39 @@
// Create and destroy a vk::UniqueInstance // Create and destroy a vk::UniqueInstance
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "01_InitInstance"; static char const * AppName = "01_InitInstance";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
try try
{ {
// initialize the vk::ApplicationInfo structure // initialize the vk::ApplicationInfo structure
vk::ApplicationInfo applicationInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1); vk::ApplicationInfo applicationInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
// initialize the vk::InstanceCreateInfo // initialize the vk::InstanceCreateInfo
vk::InstanceCreateInfo instanceCreateInfo({}, &applicationInfo); vk::InstanceCreateInfo instanceCreateInfo( {}, &applicationInfo );
// create a UniqueInstance // create a UniqueInstance
vk::UniqueInstance instance = vk::createInstanceUnique(instanceCreateInfo); vk::UniqueInstance instance = vk::createInstanceUnique( instanceCreateInfo );
// Note: No need to explicitly destroy the instance, as the corresponding destroy function is // Note: No need to explicitly destroy the instance, as the corresponding destroy function is
// called by the destructor of the UniqueInstance on leaving this scope. // called by the destructor of the UniqueInstance on leaving this scope.
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */

View File

@ -17,18 +17,19 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "02_EnumerateDevices"; static char const * AppName = "02_EnumerateDevices";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
@ -36,20 +37,20 @@ int main(int /*argc*/, char ** /*argv*/)
// enumerate the physicalDevices // enumerate the physicalDevices
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
// Note: PhysicalDevices are not created, but just enumerated. Therefore, there is nothing like a UniquePhysicalDevice. // Note: PhysicalDevices are not created, but just enumerated. Therefore, there is nothing like a
// A PhysicalDevice is unique by definition, and there's no need to destroy it. // UniquePhysicalDevice. A PhysicalDevice is unique by definition, and there's no need to destroy it.
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,18 +17,19 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "03_InitDevice"; static char const * AppName = "03_InitDevice";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
@ -39,31 +40,35 @@ int main(int /*argc*/, char ** /*argv*/)
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties(); std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
// get the first index into queueFamiliyProperties which supports graphics // get the first index into queueFamiliyProperties which supports graphics
size_t graphicsQueueFamilyIndex = std::distance(queueFamilyProperties.begin(), size_t graphicsQueueFamilyIndex = std::distance(
std::find_if(queueFamilyProperties.begin(), queueFamilyProperties.begin(),
queueFamilyProperties.end(), std::find_if(
[](vk::QueueFamilyProperties const& qfp) { return qfp.queueFlags & vk::QueueFlagBits::eGraphics; })); queueFamilyProperties.begin(), queueFamilyProperties.end(), []( vk::QueueFamilyProperties const & qfp ) {
assert(graphicsQueueFamilyIndex < queueFamilyProperties.size()); return qfp.queueFlags & vk::QueueFlagBits::eGraphics;
} ) );
assert( graphicsQueueFamilyIndex < queueFamilyProperties.size() );
// create a UniqueDevice // create a UniqueDevice
float queuePriority = 0.0f; float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), static_cast<uint32_t>(graphicsQueueFamilyIndex), 1, &queuePriority); vk::DeviceQueueCreateInfo deviceQueueCreateInfo(
vk::UniqueDevice device = physicalDevice.createDeviceUnique(vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo)); vk::DeviceQueueCreateFlags(), static_cast<uint32_t>( graphicsQueueFamilyIndex ), 1, &queuePriority );
vk::UniqueDevice device =
physicalDevice.createDeviceUnique( vk::DeviceCreateInfo( vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo ) );
// Note: No need to explicitly destroy the device, as the corresponding destroy function is // Note: No need to explicitly destroy the device, as the corresponding destroy function is
// called by the destructor of the UniqueDevice on leaving this scope. // called by the destructor of the UniqueDevice on leaving this scope.
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,47 +17,54 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "04_InitCommandBuffer"; static char const * AppName = "04_InitCommandBuffer";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
uint32_t graphicsQueueFamilyIndex = vk::su::findGraphicsQueueFamilyIndex(physicalDevice.getQueueFamilyProperties()); uint32_t graphicsQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsQueueFamilyIndex); vk::su::findGraphicsQueueFamilyIndex( physicalDevice.getQueueFamilyProperties() );
vk::UniqueDevice device = vk::su::createDevice( physicalDevice, graphicsQueueFamilyIndex );
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
// create a UniqueCommandPool to allocate a CommandBuffer from // create a UniqueCommandPool to allocate a CommandBuffer from
vk::UniqueCommandPool commandPool = device->createCommandPoolUnique(vk::CommandPoolCreateInfo(vk::CommandPoolCreateFlags(), graphicsQueueFamilyIndex)); vk::UniqueCommandPool commandPool = device->createCommandPoolUnique(
vk::CommandPoolCreateInfo( vk::CommandPoolCreateFlags(), graphicsQueueFamilyIndex ) );
// allocate a CommandBuffer from the CommandPool // allocate a CommandBuffer from the CommandPool
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
// Note: No need to explicitly free the CommandBuffer or destroy the CommandPool, as the corresponding free and destroy // Note: No need to explicitly free the CommandBuffer or destroy the CommandPool, as the corresponding free and
// functions are called by the destructor of the UniqueCommandBuffer and the UniqueCommandPool on leaving this scope. // destroy functions are called by the destructor of the UniqueCommandBuffer and the UniqueCommandPool on leaving
// this scope.
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,59 +17,66 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "05_InitSwapchain"; static char const * AppName = "05_InitSwapchain";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties(); std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
uint32_t graphicsQueueFamilyIndex = vk::su::findGraphicsQueueFamilyIndex(queueFamilyProperties); uint32_t graphicsQueueFamilyIndex = vk::su::findGraphicsQueueFamilyIndex( queueFamilyProperties );
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
uint32_t width = 64; uint32_t width = 64;
uint32_t height = 64; uint32_t height = 64;
vk::su::WindowData window = vk::su::createWindow(AppName, {width, height}); vk::su::WindowData window = vk::su::createWindow( AppName, { width, height } );
vk::UniqueSurfaceKHR surface; vk::UniqueSurfaceKHR surface;
{ {
VkSurfaceKHR _surface; VkSurfaceKHR _surface;
glfwCreateWindowSurface(VkInstance(instance.get()), window.handle, nullptr, &_surface); glfwCreateWindowSurface( VkInstance( instance.get() ), window.handle, nullptr, &_surface );
vk::ObjectDestroy<vk::Instance, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> _deleter(instance.get()); vk::ObjectDestroy<vk::Instance, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> _deleter( instance.get() );
surface = vk::UniqueSurfaceKHR(vk::SurfaceKHR(_surface), _deleter); surface = vk::UniqueSurfaceKHR( vk::SurfaceKHR( _surface ), _deleter );
} }
// determine a queueFamilyIndex that suports present // determine a queueFamilyIndex that suports present
// first check if the graphicsQueueFamiliyIndex is good enough // first check if the graphicsQueueFamiliyIndex is good enough
size_t presentQueueFamilyIndex = physicalDevice.getSurfaceSupportKHR(static_cast<uint32_t>(graphicsQueueFamilyIndex), surface.get()) ? graphicsQueueFamilyIndex : queueFamilyProperties.size(); size_t presentQueueFamilyIndex =
if (presentQueueFamilyIndex == queueFamilyProperties.size()) physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( graphicsQueueFamilyIndex ), surface.get() )
? graphicsQueueFamilyIndex
: queueFamilyProperties.size();
if ( presentQueueFamilyIndex == queueFamilyProperties.size() )
{ {
// the graphicsQueueFamilyIndex doesn't support present -> look for an other family index that supports both graphics and present // the graphicsQueueFamilyIndex doesn't support present -> look for an other family index that supports both
for (size_t i = 0; i < queueFamilyProperties.size(); i++) // graphics and present
for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
{ {
if ((queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eGraphics) && physicalDevice.getSurfaceSupportKHR(static_cast<uint32_t>(i), surface.get())) if ( ( queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eGraphics ) &&
physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), surface.get() ) )
{ {
graphicsQueueFamilyIndex = vk::su::checked_cast<uint32_t>(i); graphicsQueueFamilyIndex = vk::su::checked_cast<uint32_t>( i );
presentQueueFamilyIndex = i; presentQueueFamilyIndex = i;
break; break;
} }
} }
if (presentQueueFamilyIndex == queueFamilyProperties.size()) if ( presentQueueFamilyIndex == queueFamilyProperties.size() )
{ {
// there's nothing like a single family index that supports both graphics and present -> look for an other family index that supports present // there's nothing like a single family index that supports both graphics and present -> look for an other
for (size_t i = 0; i < queueFamilyProperties.size(); i++) // family index that supports present
for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
{ {
if (physicalDevice.getSurfaceSupportKHR(static_cast<uint32_t>(i), surface.get())) if ( physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), surface.get() ) )
{ {
presentQueueFamilyIndex = i; presentQueueFamilyIndex = i;
break; break;
@ -77,26 +84,31 @@ int main(int /*argc*/, char ** /*argv*/)
} }
} }
} }
if ((graphicsQueueFamilyIndex == queueFamilyProperties.size()) || (presentQueueFamilyIndex == queueFamilyProperties.size())) if ( ( graphicsQueueFamilyIndex == queueFamilyProperties.size() ) ||
( presentQueueFamilyIndex == queueFamilyProperties.size() ) )
{ {
throw std::runtime_error("Could not find a queue for graphics or present -> terminating"); throw std::runtime_error( "Could not find a queue for graphics or present -> terminating" );
} }
// create a device // create a device
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsQueueFamilyIndex, vk::su::getDeviceExtensions()); vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsQueueFamilyIndex, vk::su::getDeviceExtensions() );
// get the supported VkFormats // get the supported VkFormats
std::vector<vk::SurfaceFormatKHR> formats = physicalDevice.getSurfaceFormatsKHR(surface.get()); std::vector<vk::SurfaceFormatKHR> formats = physicalDevice.getSurfaceFormatsKHR( surface.get() );
assert(!formats.empty()); assert( !formats.empty() );
vk::Format format = (formats[0].format == vk::Format::eUndefined) ? vk::Format::eB8G8R8A8Unorm : formats[0].format; vk::Format format =
( formats[0].format == vk::Format::eUndefined ) ? vk::Format::eB8G8R8A8Unorm : formats[0].format;
vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.get()); vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR( surface.get() );
VkExtent2D swapchainExtent; VkExtent2D swapchainExtent;
if (surfaceCapabilities.currentExtent.width == std::numeric_limits<uint32_t>::max()) if ( surfaceCapabilities.currentExtent.width == std::numeric_limits<uint32_t>::max() )
{ {
// If the surface size is undefined, the size is set to the size of the images requested. // If the surface size is undefined, the size is set to the size of the images requested.
swapchainExtent.width = vk::su::clamp(width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width); swapchainExtent.width =
swapchainExtent.height = vk::su::clamp(height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height); vk::su::clamp( width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width );
swapchainExtent.height =
vk::su::clamp( height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height );
} }
else else
{ {
@ -107,38 +119,63 @@ int main(int /*argc*/, char ** /*argv*/)
// The FIFO present mode is guaranteed by the spec to be supported // The FIFO present mode is guaranteed by the spec to be supported
vk::PresentModeKHR swapchainPresentMode = vk::PresentModeKHR::eFifo; vk::PresentModeKHR swapchainPresentMode = vk::PresentModeKHR::eFifo;
vk::SurfaceTransformFlagBitsKHR preTransform = (surfaceCapabilities.supportedTransforms & vk::SurfaceTransformFlagBitsKHR::eIdentity) ? vk::SurfaceTransformFlagBitsKHR::eIdentity : surfaceCapabilities.currentTransform; vk::SurfaceTransformFlagBitsKHR preTransform =
( surfaceCapabilities.supportedTransforms & vk::SurfaceTransformFlagBitsKHR::eIdentity )
? vk::SurfaceTransformFlagBitsKHR::eIdentity
: surfaceCapabilities.currentTransform;
vk::CompositeAlphaFlagBitsKHR compositeAlpha = vk::CompositeAlphaFlagBitsKHR compositeAlpha =
(surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePreMultiplied) ? vk::CompositeAlphaFlagBitsKHR::ePreMultiplied : ( surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePreMultiplied )
(surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePostMultiplied) ? vk::CompositeAlphaFlagBitsKHR::ePostMultiplied : ? vk::CompositeAlphaFlagBitsKHR::ePreMultiplied
(surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::eInherit) ? vk::CompositeAlphaFlagBitsKHR::eInherit : vk::CompositeAlphaFlagBitsKHR::eOpaque; : ( surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::ePostMultiplied )
? vk::CompositeAlphaFlagBitsKHR::ePostMultiplied
: ( surfaceCapabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::eInherit )
? vk::CompositeAlphaFlagBitsKHR::eInherit
: vk::CompositeAlphaFlagBitsKHR::eOpaque;
vk::SwapchainCreateInfoKHR swapChainCreateInfo(vk::SwapchainCreateFlagsKHR(), surface.get(), surfaceCapabilities.minImageCount, format, vk::ColorSpaceKHR::eSrgbNonlinear, vk::SwapchainCreateInfoKHR swapChainCreateInfo( vk::SwapchainCreateFlagsKHR(),
swapchainExtent, 1, vk::ImageUsageFlagBits::eColorAttachment, vk::SharingMode::eExclusive, 0, nullptr, preTransform, compositeAlpha, swapchainPresentMode, true, nullptr); surface.get(),
surfaceCapabilities.minImageCount,
format,
vk::ColorSpaceKHR::eSrgbNonlinear,
swapchainExtent,
1,
vk::ImageUsageFlagBits::eColorAttachment,
vk::SharingMode::eExclusive,
0,
nullptr,
preTransform,
compositeAlpha,
swapchainPresentMode,
true,
nullptr );
uint32_t queueFamilyIndices[2] = { static_cast<uint32_t>(graphicsQueueFamilyIndex), static_cast<uint32_t>(presentQueueFamilyIndex) }; uint32_t queueFamilyIndices[2] = { static_cast<uint32_t>( graphicsQueueFamilyIndex ),
if (graphicsQueueFamilyIndex != presentQueueFamilyIndex) static_cast<uint32_t>( presentQueueFamilyIndex ) };
if ( graphicsQueueFamilyIndex != presentQueueFamilyIndex )
{ {
// If the graphics and present queues are from different queue families, we either have to explicitly transfer ownership of images between // If the graphics and present queues are from different queue families, we either have to explicitly transfer
// the queues, or we have to create the swapchain with imageSharingMode as VK_SHARING_MODE_CONCURRENT // ownership of images between the queues, or we have to create the swapchain with imageSharingMode as
swapChainCreateInfo.imageSharingMode = vk::SharingMode::eConcurrent; // VK_SHARING_MODE_CONCURRENT
swapChainCreateInfo.imageSharingMode = vk::SharingMode::eConcurrent;
swapChainCreateInfo.queueFamilyIndexCount = 2; swapChainCreateInfo.queueFamilyIndexCount = 2;
swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices; swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
} }
vk::UniqueSwapchainKHR swapChain = device->createSwapchainKHRUnique(swapChainCreateInfo); vk::UniqueSwapchainKHR swapChain = device->createSwapchainKHRUnique( swapChainCreateInfo );
std::vector<vk::Image> swapChainImages = device->getSwapchainImagesKHR(swapChain.get()); std::vector<vk::Image> swapChainImages = device->getSwapchainImagesKHR( swapChain.get() );
std::vector<vk::UniqueImageView> imageViews; std::vector<vk::UniqueImageView> imageViews;
imageViews.reserve(swapChainImages.size()); imageViews.reserve( swapChainImages.size() );
vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA); vk::ComponentMapping componentMapping(
vk::ImageSubresourceRange subResourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1); vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA );
for (auto image : swapChainImages) vk::ImageSubresourceRange subResourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 );
for ( auto image : swapChainImages )
{ {
vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), image, vk::ImageViewType::e2D, format, componentMapping, subResourceRange); vk::ImageViewCreateInfo imageViewCreateInfo(
imageViews.push_back(device->createImageViewUnique(imageViewCreateInfo)); vk::ImageViewCreateFlags(), image, vk::ImageViewType::e2D, format, componentMapping, subResourceRange );
imageViews.push_back( device->createImageViewUnique( imageViewCreateInfo ) );
} }
// Note: No need to explicitly destroy the ImageViews or the swapChain, as the corresponding destroy // Note: No need to explicitly destroy the ImageViews or the swapChain, as the corresponding destroy
@ -146,20 +183,20 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,86 +17,106 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "06_InitDepthBuffer"; static char const * AppName = "06_InitDepthBuffer";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
const vk::Format depthFormat = vk::Format::eD16Unorm; const vk::Format depthFormat = vk::Format::eD16Unorm;
vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(depthFormat); vk::FormatProperties formatProperties = physicalDevice.getFormatProperties( depthFormat );
vk::ImageTiling tiling; vk::ImageTiling tiling;
if (formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment) if ( formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment )
{ {
tiling = vk::ImageTiling::eLinear; tiling = vk::ImageTiling::eLinear;
} }
else if (formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment) else if ( formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eDepthStencilAttachment )
{ {
tiling = vk::ImageTiling::eOptimal; tiling = vk::ImageTiling::eOptimal;
} }
else else
{ {
throw std::runtime_error("DepthStencilAttachment is not supported for D16Unorm depth format."); throw std::runtime_error( "DepthStencilAttachment is not supported for D16Unorm depth format." );
} }
vk::ImageCreateInfo imageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, depthFormat, vk::Extent3D(surfaceData.extent, 1), 1, 1, vk::SampleCountFlagBits::e1, tiling, vk::ImageUsageFlagBits::eDepthStencilAttachment); vk::ImageCreateInfo imageCreateInfo( vk::ImageCreateFlags(),
vk::UniqueImage depthImage = device->createImageUnique(imageCreateInfo); vk::ImageType::e2D,
depthFormat,
vk::Extent3D( surfaceData.extent, 1 ),
1,
1,
vk::SampleCountFlagBits::e1,
tiling,
vk::ImageUsageFlagBits::eDepthStencilAttachment );
vk::UniqueImage depthImage = device->createImageUnique( imageCreateInfo );
vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties(); vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties();
vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements(depthImage.get()); vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements( depthImage.get() );
uint32_t typeBits = memoryRequirements.memoryTypeBits; uint32_t typeBits = memoryRequirements.memoryTypeBits;
uint32_t typeIndex = uint32_t(~0); uint32_t typeIndex = uint32_t( ~0 );
for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) for ( uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++ )
{ {
if ((typeBits & 1) && ((memoryProperties.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal) == vk::MemoryPropertyFlagBits::eDeviceLocal)) if ( ( typeBits & 1 ) &&
( ( memoryProperties.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal ) ==
vk::MemoryPropertyFlagBits::eDeviceLocal ) )
{ {
typeIndex = i; typeIndex = i;
break; break;
} }
typeBits >>= 1; typeBits >>= 1;
} }
assert(typeIndex != ~0); assert( typeIndex != ~0 );
vk::UniqueDeviceMemory depthMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, typeIndex)); vk::UniqueDeviceMemory depthMemory =
device->allocateMemoryUnique( vk::MemoryAllocateInfo( memoryRequirements.size, typeIndex ) );
device->bindImageMemory(depthImage.get(), depthMemory.get(), 0); device->bindImageMemory( depthImage.get(), depthMemory.get(), 0 );
vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA); vk::ComponentMapping componentMapping(
vk::ImageSubresourceRange subResourceRange(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1); vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA );
vk::UniqueImageView depthView = device->createImageViewUnique(vk::ImageViewCreateInfo(vk::ImageViewCreateFlags(), depthImage.get(), vk::ImageViewType::e2D, depthFormat, componentMapping, subResourceRange)); vk::ImageSubresourceRange subResourceRange( vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1 );
vk::UniqueImageView depthView = device->createImageViewUnique( vk::ImageViewCreateInfo( vk::ImageViewCreateFlags(),
depthImage.get(),
vk::ImageViewType::e2D,
depthFormat,
componentMapping,
subResourceRange ) );
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,67 +17,92 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#define GLM_FORCE_RADIANS #define GLM_FORCE_RADIANS
#pragma warning(disable:4201) // disable warning C4201: nonstandard extension used: nameless struct/union; needed to get glm/detail/type_vec?.hpp without warnings #pragma warning( disable : 4201 ) // disable warning C4201: nonstandard extension used: nameless struct/union; needed
// to get glm/detail/type_vec?.hpp without warnings
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
static char const* AppName = "07_InitUniformBuffer"; static char const * AppName = "07_InitUniformBuffer";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, vk::su::findGraphicsQueueFamilyIndex(physicalDevice.getQueueFamilyProperties())); vk::UniqueDevice device = vk::su::createDevice(
physicalDevice, vk::su::findGraphicsQueueFamilyIndex( physicalDevice.getQueueFamilyProperties() ) );
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
glm::mat4x4 model = glm::mat4x4(1.0f); glm::mat4x4 model = glm::mat4x4( 1.0f );
glm::mat4x4 view = glm::lookAt(glm::vec3(-5.0f, 3.0f, -10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)); glm::mat4x4 view =
glm::mat4x4 projection = glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 100.0f); glm::lookAt( glm::vec3( -5.0f, 3.0f, -10.0f ), glm::vec3( 0.0f, 0.0f, 0.0f ), glm::vec3( 0.0f, -1.0f, 0.0f ) );
glm::mat4x4 clip = glm::mat4x4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f); // vulkan clip space has inverted y and half z ! glm::mat4x4 projection = glm::perspective( glm::radians( 45.0f ), 1.0f, 0.1f, 100.0f );
glm::mat4x4 mvpc = clip * projection * view * model; glm::mat4x4 clip = glm::mat4x4( 1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
-1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
0.5f,
0.0f,
0.0f,
0.0f,
0.5f,
1.0f ); // vulkan clip space has inverted y and half z !
glm::mat4x4 mvpc = clip * projection * view * model;
vk::UniqueBuffer uniformDataBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(mvpc), vk::BufferUsageFlagBits::eUniformBuffer)); vk::UniqueBuffer uniformDataBuffer = device->createBufferUnique(
vk::BufferCreateInfo( vk::BufferCreateFlags(), sizeof( mvpc ), vk::BufferUsageFlagBits::eUniformBuffer ) );
vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements(uniformDataBuffer.get()); vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements( uniformDataBuffer.get() );
uint32_t typeIndex = vk::su::findMemoryType(physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); uint32_t typeIndex =
vk::UniqueDeviceMemory uniformDataMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, typeIndex)); vk::su::findMemoryType( physicalDevice.getMemoryProperties(),
memoryRequirements.memoryTypeBits,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent );
vk::UniqueDeviceMemory uniformDataMemory =
device->allocateMemoryUnique( vk::MemoryAllocateInfo( memoryRequirements.size, typeIndex ) );
uint8_t* pData = static_cast<uint8_t*>(device->mapMemory(uniformDataMemory.get(), 0, memoryRequirements.size)); uint8_t * pData =
memcpy(pData, &mvpc, sizeof(mvpc)); static_cast<uint8_t *>( device->mapMemory( uniformDataMemory.get(), 0, memoryRequirements.size ) );
device->unmapMemory(uniformDataMemory.get()); memcpy( pData, &mvpc, sizeof( mvpc ) );
device->unmapMemory( uniformDataMemory.get() );
device->bindBufferMemory(uniformDataBuffer.get(), uniformDataMemory.get(), 0); device->bindBufferMemory( uniformDataBuffer.get(), uniformDataMemory.get(), 0 );
// Note: No need to explicitly destroy the memory or the buffer, as the corresponding destroy function is // Note: No need to explicitly destroy the memory or the buffer, as the corresponding destroy function is
// called by the destructor of the UniqueMemory or UniqueBuffer, respectively, on leaving this scope. // called by the destructor of the UniqueMemory or UniqueBuffer, respectively, on leaving this scope.
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,52 +17,58 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "08_InitPipelineLayout"; static char const * AppName = "08_InitPipelineLayout";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, vk::su::findGraphicsQueueFamilyIndex(physicalDevice.getQueueFamilyProperties())); vk::UniqueDevice device = vk::su::createDevice(
physicalDevice, vk::su::findGraphicsQueueFamilyIndex( physicalDevice.getQueueFamilyProperties() ) );
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
// create a DescriptorSetLayout // create a DescriptorSetLayout
vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex); vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), 1, &descriptorSetLayoutBinding)); 0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex );
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(
vk::DescriptorSetLayoutCreateInfo( vk::DescriptorSetLayoutCreateFlags(), 1, &descriptorSetLayoutBinding ) );
// create a PipelineLayout using that DescriptorSetLayout // create a PipelineLayout using that DescriptorSetLayout
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
// Note: No need to explicitly destroy the layouts, as the corresponding destroy function is // Note: No need to explicitly destroy the layouts, as the corresponding destroy function is
// called by the destructor of the UniqueDescriptorSetLayout or UniquePipelineLayout, respectively, on leaving this scope. // called by the destructor of the UniqueDescriptorSetLayout or UniquePipelineLayout, respectively, on leaving this
// scope.
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -18,61 +18,73 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#define GLM_FORCE_RADIANS #define GLM_FORCE_RADIANS
#pragma warning(disable:4201) // disable warning C4201: nonstandard extension used: nameless struct/union; needed to get glm/detail/type_vec?.hpp without warnings #pragma warning( disable : 4201 ) // disable warning C4201: nonstandard extension used: nameless struct/union; needed
// to get glm/detail/type_vec?.hpp without warnings
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
static char const* AppName = "09_InitDescriptorSet"; static char const * AppName = "09_InitDescriptorSet";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, vk::su::findGraphicsQueueFamilyIndex(physicalDevice.getQueueFamilyProperties())); vk::UniqueDevice device = vk::su::createDevice(
physicalDevice, vk::su::findGraphicsQueueFamilyIndex( physicalDevice.getQueueFamilyProperties() ) );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(vk::Extent2D(0, 0))); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( vk::Extent2D( 0, 0 ) ) );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, { {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex} }); vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
device, { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex } } );
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
// create a descriptor pool // create a descriptor pool
vk::DescriptorPoolSize poolSize(vk::DescriptorType::eUniformBuffer, 1); vk::DescriptorPoolSize poolSize( vk::DescriptorType::eUniformBuffer, 1 );
vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 1, &poolSize)); vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(
vk::DescriptorPoolCreateInfo( vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 1, &poolSize ) );
// allocate a descriptor set // allocate a descriptor set
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::DescriptorBufferInfo descriptorBufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); vk::DescriptorBufferInfo descriptorBufferInfo( uniformBufferData.buffer.get(), 0, sizeof( glm::mat4x4 ) );
device->updateDescriptorSets(vk::WriteDescriptorSet(descriptorSet.get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &descriptorBufferInfo), {}); device->updateDescriptorSets(
vk::WriteDescriptorSet(
descriptorSet.get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &descriptorBufferInfo ),
{} );
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,67 +17,94 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#define GLM_FORCE_RADIANS #define GLM_FORCE_RADIANS
#pragma warning(disable:4201) // disable warning C4201: nonstandard extension used: nameless struct/union; needed to get glm/detail/type_vec?.hpp without warnings #pragma warning( disable : 4201 ) // disable warning C4201: nonstandard extension used: nameless struct/union; needed
// to get glm/detail/type_vec?.hpp without warnings
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
static char const* AppName = "10_InitRenderPass"; static char const * AppName = "10_InitRenderPass";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(64, 64)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 64, 64 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::Format colorFormat = vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format; vk::Format colorFormat =
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format;
vk::Format depthFormat = vk::Format::eD16Unorm; vk::Format depthFormat = vk::Format::eD16Unorm;
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
vk::AttachmentDescription attachmentDescriptions[2]; vk::AttachmentDescription attachmentDescriptions[2];
attachmentDescriptions[0] = vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, attachmentDescriptions[0] = vk::AttachmentDescription( vk::AttachmentDescriptionFlags(),
vk::AttachmentStoreOp::eStore, vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR); colorFormat,
attachmentDescriptions[1] = vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), depthFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, vk::SampleCountFlagBits::e1,
vk::AttachmentStoreOp::eDontCare, vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::AttachmentLoadOp::eClear,
vk::AttachmentStoreOp::eStore,
vk::AttachmentLoadOp::eDontCare,
vk::AttachmentStoreOp::eDontCare,
vk::ImageLayout::eUndefined,
vk::ImageLayout::ePresentSrcKHR );
attachmentDescriptions[1] = vk::AttachmentDescription( vk::AttachmentDescriptionFlags(),
depthFormat,
vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eClear,
vk::AttachmentStoreOp::eDontCare,
vk::AttachmentLoadOp::eDontCare,
vk::AttachmentStoreOp::eDontCare,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eDepthStencilAttachmentOptimal );
vk::AttachmentReference colorReference(0, vk::ImageLayout::eColorAttachmentOptimal); vk::AttachmentReference colorReference( 0, vk::ImageLayout::eColorAttachmentOptimal );
vk::AttachmentReference depthReference(1, vk::ImageLayout::eDepthStencilAttachmentOptimal); vk::AttachmentReference depthReference( 1, vk::ImageLayout::eDepthStencilAttachmentOptimal );
vk::SubpassDescription subpass(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 0, nullptr, 1, &colorReference, nullptr, &depthReference); vk::SubpassDescription subpass( vk::SubpassDescriptionFlags(),
vk::PipelineBindPoint::eGraphics,
0,
nullptr,
1,
&colorReference,
nullptr,
&depthReference );
vk::UniqueRenderPass renderPass = device->createRenderPassUnique(vk::RenderPassCreateInfo(vk::RenderPassCreateFlags(), 2, attachmentDescriptions, 1, &subpass)); vk::UniqueRenderPass renderPass = device->createRenderPassUnique(
vk::RenderPassCreateInfo( vk::RenderPassCreateFlags(), 2, attachmentDescriptions, 1, &subpass ) );
// Note: No need to explicitly destroy the RenderPass or the Semaphore, as the corresponding destroy // Note: No need to explicitly destroy the RenderPass or the Semaphore, as the corresponding destroy
// functions are called by the destructor of the UniqueRenderPass and the UniqueSemaphore on leaving this scope. // functions are called by the destructor of the UniqueRenderPass and the UniqueSemaphore on leaving this scope.
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,43 +17,47 @@
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "11_InitShaders"; static char const * AppName = "11_InitShaders";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, vk::su::findGraphicsQueueFamilyIndex(physicalDevice.getQueueFamilyProperties())); vk::UniqueDevice device = vk::su::createDevice(
physicalDevice, vk::su::findGraphicsQueueFamilyIndex( physicalDevice.getQueueFamilyProperties() ) );
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
glslang::InitializeProcess(); glslang::InitializeProcess();
std::vector<unsigned int> vertexShaderSPV; std::vector<unsigned int> vertexShaderSPV;
bool ok = vk::su::GLSLtoSPV(vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C, vertexShaderSPV); bool ok = vk::su::GLSLtoSPV( vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C, vertexShaderSPV );
assert(ok); assert( ok );
vk::ShaderModuleCreateInfo vertexShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), vertexShaderSPV.size() * sizeof(unsigned int), vertexShaderSPV.data()); vk::ShaderModuleCreateInfo vertexShaderModuleCreateInfo(
vk::UniqueShaderModule vertexShaderModule = device->createShaderModuleUnique(vertexShaderModuleCreateInfo); vk::ShaderModuleCreateFlags(), vertexShaderSPV.size() * sizeof( unsigned int ), vertexShaderSPV.data() );
vk::UniqueShaderModule vertexShaderModule = device->createShaderModuleUnique( vertexShaderModuleCreateInfo );
std::vector<unsigned int> fragmentShaderSPV; std::vector<unsigned int> fragmentShaderSPV;
ok = vk::su::GLSLtoSPV(vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C, fragmentShaderSPV); ok = vk::su::GLSLtoSPV( vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C, fragmentShaderSPV );
assert(ok); assert( ok );
vk::ShaderModuleCreateInfo fragmentShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), fragmentShaderSPV.size() * sizeof(unsigned int), fragmentShaderSPV.data()); vk::ShaderModuleCreateInfo fragmentShaderModuleCreateInfo(
vk::UniqueShaderModule fragmentShaderModule = device->createShaderModuleUnique(fragmentShaderModuleCreateInfo); vk::ShaderModuleCreateFlags(), fragmentShaderSPV.size() * sizeof( unsigned int ), fragmentShaderSPV.data() );
vk::UniqueShaderModule fragmentShaderModule = device->createShaderModuleUnique( fragmentShaderModuleCreateInfo );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
@ -62,20 +66,20 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,33 +17,44 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "12_InitFrameBuffers"; static char const * AppName = "12_InitFrameBuffers";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(64, 64)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 64, 64 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, swapChainData.colorFormat, depthBufferData.format); vk::UniqueRenderPass renderPass =
vk::su::createRenderPass( device, swapChainData.colorFormat, depthBufferData.format );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
@ -51,31 +62,38 @@ int main(int /*argc*/, char ** /*argv*/)
attachments[1] = depthBufferData.imageView.get(); attachments[1] = depthBufferData.imageView.get();
std::vector<vk::UniqueFramebuffer> framebuffers; std::vector<vk::UniqueFramebuffer> framebuffers;
framebuffers.reserve(swapChainData.imageViews.size()); framebuffers.reserve( swapChainData.imageViews.size() );
for (auto const& view : swapChainData.imageViews) for ( auto const & view : swapChainData.imageViews )
{ {
attachments[0] = view.get(); attachments[0] = view.get();
framebuffers.push_back(device->createFramebufferUnique(vk::FramebufferCreateInfo(vk::FramebufferCreateFlags(), renderPass.get(), 2, attachments, surfaceData.extent.width, surfaceData.extent.height, 1))); framebuffers.push_back( device->createFramebufferUnique( vk::FramebufferCreateInfo( vk::FramebufferCreateFlags(),
renderPass.get(),
2,
attachments,
surfaceData.extent.width,
surfaceData.extent.height,
1 ) ) );
} }
// Note: No need to explicitly destroy the Framebuffers, as the destroy functions are called by the destructor of the UniqueFramebuffer on leaving this scope. // Note: No need to explicitly destroy the Framebuffers, as the destroy functions are called by the destructor of
// the UniqueFramebuffer on leaving this scope.
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -18,98 +18,125 @@
#include "../utils/geometries.hpp" #include "../utils/geometries.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "13_InitVertexBuffer"; static char const * AppName = "13_InitVertexBuffer";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(64, 64)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 64, 64 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, swapChainData.colorFormat, depthBufferData.format); vk::UniqueRenderPass renderPass =
vk::su::createRenderPass( device, swapChainData.colorFormat, depthBufferData.format );
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// create a vertex buffer for some vertex and color data // create a vertex buffer for some vertex and color data
vk::UniqueBuffer vertexBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(coloredCubeData), vk::BufferUsageFlagBits::eVertexBuffer)); vk::UniqueBuffer vertexBuffer = device->createBufferUnique( vk::BufferCreateInfo(
vk::BufferCreateFlags(), sizeof( coloredCubeData ), vk::BufferUsageFlagBits::eVertexBuffer ) );
// allocate device memory for that buffer // allocate device memory for that buffer
vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements(vertexBuffer.get()); vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements( vertexBuffer.get() );
uint32_t memoryTypeIndex = vk::su::findMemoryType(physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); uint32_t memoryTypeIndex =
vk::UniqueDeviceMemory deviceMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); vk::su::findMemoryType( physicalDevice.getMemoryProperties(),
memoryRequirements.memoryTypeBits,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent );
vk::UniqueDeviceMemory deviceMemory =
device->allocateMemoryUnique( vk::MemoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ) );
// copy the vertex and color data into that device memory // copy the vertex and color data into that device memory
uint8_t *pData = static_cast<uint8_t*>(device->mapMemory(deviceMemory.get(), 0, memoryRequirements.size)); uint8_t * pData = static_cast<uint8_t *>( device->mapMemory( deviceMemory.get(), 0, memoryRequirements.size ) );
memcpy(pData, coloredCubeData, sizeof(coloredCubeData)); memcpy( pData, coloredCubeData, sizeof( coloredCubeData ) );
device->unmapMemory(deviceMemory.get()); device->unmapMemory( deviceMemory.get() );
// and bind the device memory to the vertex buffer // and bind the device memory to the vertex buffer
device->bindBufferMemory(vertexBuffer.get(), deviceMemory.get(), 0); device->bindBufferMemory( vertexBuffer.get(), deviceMemory.get(), 0 );
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo(vk::SemaphoreCreateFlags())); vk::UniqueSemaphore imageAcquiredSemaphore =
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); device->createSemaphoreUnique( vk::SemaphoreCreateInfo( vk::SemaphoreCreateFlags() ) );
assert(currentBuffer.result == vk::Result::eSuccess); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.value < framebuffers.size()); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); commandBuffer->begin( vk::CommandBufferBeginInfo( vk::CommandBufferUsageFlags() ) );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); framebuffers[currentBuffer.value].get(),
vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
2,
clearValues );
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindVertexBuffers(0, *vertexBuffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBuffer, { 0 } );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::su::submitAndWait(device, graphicsQueue, commandBuffer); vk::su::submitAndWait( device, graphicsQueue, commandBuffer );
// Note: No need to explicitly destroy the vertexBuffer, deviceMemory, or semaphore, as the destroy functions are called // Note: No need to explicitly destroy the vertexBuffer, deviceMemory, or semaphore, as the destroy functions are
// by the destructor of the UniqueBuffer, UniqueDeviceMemory, and UniqueSemaphore, respectively, on leaving this scope. // called by the destructor of the UniqueBuffer, UniqueDeviceMemory, and UniqueSemaphore, respectively, on leaving
// this scope.
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,55 +19,64 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "14_InitPipeline"; static char const * AppName = "14_InitPipeline";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, vk::Format::eD16Unorm); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
vk::Format::eD16Unorm );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, { {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex} }); vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); device, { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
vk::PipelineShaderStageCreateInfo pipelineShaderStageCreateInfos[2] = vk::PipelineShaderStageCreateInfo pipelineShaderStageCreateInfos[2] = {
{ vk::PipelineShaderStageCreateInfo(
vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, vertexShaderModule.get(), "main"), vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, vertexShaderModule.get(), "main" ),
vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule.get(), "main") vk::PipelineShaderStageCreateInfo(
vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule.get(), "main" )
}; };
vk::VertexInputBindingDescription vertexInputBindingDescription(0, sizeof(coloredCubeData[0])); vk::VertexInputBindingDescription vertexInputBindingDescription( 0, sizeof( coloredCubeData[0] ) );
vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[2] = vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
{ vk::VertexInputAttributeDescription( 0, 0, vk::Format::eR32G32B32A32Sfloat, 0 ),
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32A32Sfloat, 0), vk::VertexInputAttributeDescription( 1, 0, vk::Format::eR32G32B32A32Sfloat, 16 )
vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32A32Sfloat, 16)
}; };
vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(
(
vk::PipelineVertexInputStateCreateFlags(), // flags vk::PipelineVertexInputStateCreateFlags(), // flags
1, // vertexBindingDescriptionCount 1, // vertexBindingDescriptionCount
&vertexInputBindingDescription, // pVertexBindingDescription &vertexInputBindingDescription, // pVertexBindingDescription
@ -75,12 +84,13 @@ int main(int /*argc*/, char ** /*argv*/)
vertexInputAttributeDescriptions // pVertexAttributeDescriptions vertexInputAttributeDescriptions // pVertexAttributeDescriptions
); );
vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleList); vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(
vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleList );
vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(vk::PipelineViewportStateCreateFlags(), 1, nullptr, 1, nullptr); vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(
vk::PipelineViewportStateCreateFlags(), 1, nullptr, 1, nullptr );
vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo(
(
vk::PipelineRasterizationStateCreateFlags(), // flags vk::PipelineRasterizationStateCreateFlags(), // flags
false, // depthClampEnable false, // depthClampEnable
false, // rasterizerDiscardEnable false, // rasterizerDiscardEnable
@ -94,87 +104,85 @@ int main(int /*argc*/, char ** /*argv*/)
1.0f // lineWidth 1.0f // lineWidth
); );
vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo(
(
vk::PipelineMultisampleStateCreateFlags(), // flags vk::PipelineMultisampleStateCreateFlags(), // flags
vk::SampleCountFlagBits::e1 // rasterizationSamples vk::SampleCountFlagBits::e1 // rasterizationSamples
// other values can be default // other values can be default
); );
vk::StencilOpState stencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways); vk::StencilOpState stencilOpState(
vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways );
( vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo(
vk::PipelineDepthStencilStateCreateFlags(), // flags vk::PipelineDepthStencilStateCreateFlags(), // flags
true, // depthTestEnable true, // depthTestEnable
true, // depthWriteEnable true, // depthWriteEnable
vk::CompareOp::eLessOrEqual, // depthCompareOp vk::CompareOp::eLessOrEqual, // depthCompareOp
false, // depthBoundTestEnable false, // depthBoundTestEnable
false, // stencilTestEnable false, // stencilTestEnable
stencilOpState, // front stencilOpState, // front
stencilOpState // back stencilOpState // back
); );
vk::ColorComponentFlags colorComponentFlags(vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA); vk::ColorComponentFlags colorComponentFlags( vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA );
( vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState(
false, // blendEnable false, // blendEnable
vk::BlendFactor::eZero, // srcColorBlendFactor vk::BlendFactor::eZero, // srcColorBlendFactor
vk::BlendFactor::eZero, // dstColorBlendFactor vk::BlendFactor::eZero, // dstColorBlendFactor
vk::BlendOp::eAdd, // colorBlendOp vk::BlendOp::eAdd, // colorBlendOp
vk::BlendFactor::eZero, // srcAlphaBlendFactor vk::BlendFactor::eZero, // srcAlphaBlendFactor
vk::BlendFactor::eZero, // dstAlphaBlendFactor vk::BlendFactor::eZero, // dstAlphaBlendFactor
vk::BlendOp::eAdd, // alphaBlendOp vk::BlendOp::eAdd, // alphaBlendOp
colorComponentFlags // colorWriteMask colorComponentFlags // colorWriteMask
); );
vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo(
( vk::PipelineColorBlendStateCreateFlags(), // flags
vk::PipelineColorBlendStateCreateFlags(), // flags false, // logicOpEnable
false, // logicOpEnable vk::LogicOp::eNoOp, // logicOp
vk::LogicOp::eNoOp, // logicOp 1, // attachmentCount
1, // attachmentCount &pipelineColorBlendAttachmentState, // pAttachments
&pipelineColorBlendAttachmentState, // pAttachments { { 1.0f, 1.0f, 1.0f, 1.0f } } // blendConstants
{ { 1.0f, 1.0f, 1.0f, 1.0f } } // blendConstants
); );
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates); vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(
vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates );
vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo(
( vk::PipelineCreateFlags(), // flags
vk::PipelineCreateFlags(), // flags 2, // stageCount
2, // stageCount pipelineShaderStageCreateInfos, // pStages
pipelineShaderStageCreateInfos, // pStages &pipelineVertexInputStateCreateInfo, // pVertexInputState
&pipelineVertexInputStateCreateInfo, // pVertexInputState &pipelineInputAssemblyStateCreateInfo, // pInputAssemblyState
&pipelineInputAssemblyStateCreateInfo, // pInputAssemblyState nullptr, // pTessellationState
nullptr, // pTessellationState &pipelineViewportStateCreateInfo, // pViewportState
&pipelineViewportStateCreateInfo, // pViewportState &pipelineRasterizationStateCreateInfo, // pRasterizationState
&pipelineRasterizationStateCreateInfo, // pRasterizationState &pipelineMultisampleStateCreateInfo, // pMultisampleState
&pipelineMultisampleStateCreateInfo, // pMultisampleState &pipelineDepthStencilStateCreateInfo, // pDepthStencilState
&pipelineDepthStencilStateCreateInfo, // pDepthStencilState &pipelineColorBlendStateCreateInfo, // pColorBlendState
&pipelineColorBlendStateCreateInfo, // pColorBlendState &pipelineDynamicStateCreateInfo, // pDynamicState
&pipelineDynamicStateCreateInfo, // pDynamicState pipelineLayout.get(), // layout
pipelineLayout.get(), // layout renderPass.get() // renderPass
renderPass.get() // renderPass
); );
vk::UniquePipeline pipeline = device->createGraphicsPipelineUnique(nullptr, graphicsPipelineCreateInfo); vk::UniquePipeline pipeline = device->createGraphicsPipelineUnique( nullptr, graphicsPipelineCreateInfo );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError &err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,124 +19,179 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "15_DrawCube"; static char const * AppName = "15_DrawCube";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, { {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex} }); vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); device, { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(coloredCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, coloredCubeData, sizeof(coloredCubeData) / sizeof(coloredCubeData[0])); physicalDevice, device, sizeof( coloredCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
coloredCubeData,
sizeof( coloredCubeData ) / sizeof( coloredCubeData[0] ) );
vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, { {vk::DescriptorType::eUniformBuffer, 1} }); vk::UniqueDescriptorPool descriptorPool =
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); vk::su::createDescriptorPool( device, { { vk::DescriptorType::eUniformBuffer, 1 } } );
vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::su::updateDescriptorSets(device, descriptorSet, {{vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView()}}, {}); vk::su::updateDescriptorSets(
device,
descriptorSet,
{ { vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView() } },
{} );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(
sizeof(coloredCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32B32A32Sfloat, 16 } }, device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( coloredCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32B32A32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); commandBuffer->begin( vk::CommandBufferBeginInfo( vk::CommandBufferUsageFlags() ) );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); framebuffers[currentBuffer.value].get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr); 2,
clearValues );
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -18,98 +18,108 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
static char const* AppName = "16_Vulkan_1_1"; static char const * AppName = "16_Vulkan_1_1";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Keep track of the major/minor version we can actually use // Keep track of the major/minor version we can actually use
uint16_t usingMajorVersion = 1; uint16_t usingMajorVersion = 1;
uint16_t usingMinorVersion = 0; uint16_t usingMinorVersion = 0;
std::string usingVersionString = ""; std::string usingVersionString = "";
// Set the desired version we want // Set the desired version we want
uint16_t desiredMajorVersion = 1; uint16_t desiredMajorVersion = 1;
uint16_t desiredMinorVersion = 1; uint16_t desiredMinorVersion = 1;
uint32_t desiredVersion = VK_MAKE_VERSION(desiredMajorVersion, desiredMinorVersion, 0); uint32_t desiredVersion = VK_MAKE_VERSION( desiredMajorVersion, desiredMinorVersion, 0 );
std::string desiredVersionString = ""; std::string desiredVersionString = "";
desiredVersionString += std::to_string(desiredMajorVersion); desiredVersionString += std::to_string( desiredMajorVersion );
desiredVersionString += "."; desiredVersionString += ".";
desiredVersionString += std::to_string(desiredMinorVersion); desiredVersionString += std::to_string( desiredMinorVersion );
#if (VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1) #if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
// initialize the DipatchLoaderDynamic to use // initialize the DipatchLoaderDynamic to use
static vk::DynamicLoader dl; static vk::DynamicLoader dl;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); dl.getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" );
VULKAN_HPP_DEFAULT_DISPATCHER.init( vkGetInstanceProcAddr );
#endif #endif
// Determine what API version is available // Determine what API version is available
uint32_t apiVersion = vk::enumerateInstanceVersion(); uint32_t apiVersion = vk::enumerateInstanceVersion();
// Translate the version into major/minor for easier comparison // Translate the version into major/minor for easier comparison
uint32_t loader_major_version = VK_VERSION_MAJOR(apiVersion); uint32_t loader_major_version = VK_VERSION_MAJOR( apiVersion );
uint32_t loader_minor_version = VK_VERSION_MINOR(apiVersion); uint32_t loader_minor_version = VK_VERSION_MINOR( apiVersion );
std::cout << "Loader/Runtime support detected for Vulkan " << loader_major_version << "." << loader_minor_version << "\n"; std::cout << "Loader/Runtime support detected for Vulkan " << loader_major_version << "." << loader_minor_version
<< "\n";
// Check current version against what we want to run // Check current version against what we want to run
if (loader_major_version > desiredMajorVersion || if ( loader_major_version > desiredMajorVersion ||
(loader_major_version == desiredMajorVersion && loader_minor_version >= desiredMinorVersion)) ( loader_major_version == desiredMajorVersion && loader_minor_version >= desiredMinorVersion ) )
{ {
// Create the instance // Create the instance
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions(), desiredVersion); vk::UniqueInstance instance =
#if !defined(NDEBUG) vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions(), desiredVersion );
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
// Get the list of physical devices // Get the list of physical devices
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices(); std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
// Go through the list of physical devices and select only those that are capable of running the API version we want. // Go through the list of physical devices and select only those that are capable of running the API version we
// want.
std::vector<vk::PhysicalDevice> desiredPhysicalDevices; std::vector<vk::PhysicalDevice> desiredPhysicalDevices;
std::copy_if(physicalDevices.begin(), physicalDevices.end(), std::back_inserter(desiredPhysicalDevices), [desiredVersion](vk::PhysicalDevice const& pd) { return pd.getProperties().apiVersion >= desiredVersion; }); std::copy_if(
physicalDevices.begin(),
physicalDevices.end(),
std::back_inserter( desiredPhysicalDevices ),
[desiredVersion]( vk::PhysicalDevice const & pd ) { return pd.getProperties().apiVersion >= desiredVersion; } );
// If we have something in the desired version physical device list, we're good // If we have something in the desired version physical device list, we're good
if (desiredPhysicalDevices.size() > 0) if ( desiredPhysicalDevices.size() > 0 )
{ {
usingMajorVersion = desiredMajorVersion; usingMajorVersion = desiredMajorVersion;
usingMinorVersion = desiredMinorVersion; usingMinorVersion = desiredMinorVersion;
} }
} }
usingVersionString += std::to_string(usingMajorVersion); usingVersionString += std::to_string( usingMajorVersion );
usingVersionString += "."; usingVersionString += ".";
usingVersionString += std::to_string(usingMinorVersion); usingVersionString += std::to_string( usingMinorVersion );
if (usingMinorVersion < desiredMinorVersion) if ( usingMinorVersion < desiredMinorVersion )
{ {
std::cout << "Determined that this system can only use Vulkan API version " << usingVersionString << " instead of desired version " << desiredVersionString << std::endl; std::cout << "Determined that this system can only use Vulkan API version " << usingVersionString
<< " instead of desired version " << desiredVersionString << std::endl;
} }
else else
{ {
std::cout << "Determined that this system can run desired Vulkan API version " << desiredVersionString << std::endl; std::cout << "Determined that this system can run desired Vulkan API version " << desiredVersionString
<< std::endl;
} }
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -20,156 +20,236 @@
#include <thread> #include <thread>
static char const* AppName = "CopyBlitImage"; static char const * AppName = "CopyBlitImage";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(640, 640)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 640, 640 ) );
vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR(surfaceData.surface.get()); vk::SurfaceCapabilitiesKHR surfaceCapabilities =
if (!(surfaceCapabilities.supportedUsageFlags & vk::ImageUsageFlagBits::eTransferDst)) physicalDevice.getSurfaceCapabilitiesKHR( surfaceData.surface.get() );
if ( !( surfaceCapabilities.supportedUsageFlags & vk::ImageUsageFlagBits::eTransferDst ) )
{ {
std::cout << "Surface cannot be destination of blit - abort \n"; std::cout << "Surface cannot be destination of blit - abort \n";
exit(-1); exit( -1 );
} }
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferDst, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferDst,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(swapChainData.colorFormat); vk::FormatProperties formatProperties = physicalDevice.getFormatProperties( swapChainData.colorFormat );
assert((formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eBlitSrc) && "Format cannot be used as transfer source"); assert( ( formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eBlitSrc ) &&
"Format cannot be used as transfer source" );
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::ResultValue<uint32_t> nextImage = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> nextImage = device->acquireNextImageKHR(
assert(nextImage.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(nextImage.value < swapChainData.images.size()); assert( nextImage.result == vk::Result::eSuccess );
assert( nextImage.value < swapChainData.images.size() );
uint32_t currentBuffer = nextImage.value; uint32_t currentBuffer = nextImage.value;
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
vk::su::setImageLayout(commandBuffer, swapChainData.images[currentBuffer], swapChainData.colorFormat, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); vk::su::setImageLayout( commandBuffer,
swapChainData.images[currentBuffer],
swapChainData.colorFormat,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eTransferDstOptimal );
// Create an image, map it, and write some values to the image // Create an image, map it, and write some values to the image
vk::ImageCreateInfo imageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, swapChainData.colorFormat, vk::Extent3D(surfaceData.extent, 1), 1, 1, vk::SampleCountFlagBits::e1, vk::ImageTiling::eLinear, vk::ImageUsageFlagBits::eTransferSrc); vk::ImageCreateInfo imageCreateInfo( vk::ImageCreateFlags(),
vk::UniqueImage blitSourceImage = device->createImageUnique(imageCreateInfo); vk::ImageType::e2D,
swapChainData.colorFormat,
vk::Extent3D( surfaceData.extent, 1 ),
1,
1,
vk::SampleCountFlagBits::e1,
vk::ImageTiling::eLinear,
vk::ImageUsageFlagBits::eTransferSrc );
vk::UniqueImage blitSourceImage = device->createImageUnique( imageCreateInfo );
vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties(); vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties();
vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements(blitSourceImage.get()); vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements( blitSourceImage.get() );
uint32_t memoryTypeIndex = vk::su::findMemoryType(memoryProperties, memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible); uint32_t memoryTypeIndex = vk::su::findMemoryType(
memoryProperties, memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible );
vk::UniqueDeviceMemory deviceMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); vk::UniqueDeviceMemory deviceMemory =
device->bindImageMemory(blitSourceImage.get(), deviceMemory.get(), 0); device->allocateMemoryUnique( vk::MemoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ) );
device->bindImageMemory( blitSourceImage.get(), deviceMemory.get(), 0 );
vk::su::setImageLayout(commandBuffer, blitSourceImage.get(), swapChainData.colorFormat, vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral); vk::su::setImageLayout( commandBuffer,
blitSourceImage.get(),
swapChainData.colorFormat,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral );
commandBuffer->end(); commandBuffer->end();
/* Queue the command buffer for execution */ /* Queue the command buffer for execution */
vk::UniqueFence commandFence = device->createFenceUnique({}); vk::UniqueFence commandFence = device->createFenceUnique( {} );
vk::PipelineStageFlags pipeStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags pipeStageFlags( vk::PipelineStageFlagBits::eColorAttachmentOutput );
graphicsQueue.submit(vk::SubmitInfo(1, &imageAcquiredSemaphore.get(), &pipeStageFlags, 1, &commandBuffer.get()), commandFence.get()); graphicsQueue.submit( vk::SubmitInfo( 1, &imageAcquiredSemaphore.get(), &pipeStageFlags, 1, &commandBuffer.get() ),
commandFence.get() );
/* Make sure command buffer is finished before mapping */ /* Make sure command buffer is finished before mapping */
while (device->waitForFences(commandFence.get(), true, vk::su::FenceTimeout) == vk::Result::eTimeout) while ( device->waitForFences( commandFence.get(), true, vk::su::FenceTimeout ) == vk::Result::eTimeout )
; ;
unsigned char* pImageMemory = static_cast<unsigned char*>(device->mapMemory(deviceMemory.get(), 0, memoryRequirements.size)); unsigned char * pImageMemory =
static_cast<unsigned char *>( device->mapMemory( deviceMemory.get(), 0, memoryRequirements.size ) );
// Checkerboard of 8x8 pixel squares // Checkerboard of 8x8 pixel squares
for (uint32_t row = 0; row < surfaceData.extent.height; row++) for ( uint32_t row = 0; row < surfaceData.extent.height; row++ )
{ {
for (uint32_t col = 0; col < surfaceData.extent.width; col++) for ( uint32_t col = 0; col < surfaceData.extent.width; col++ )
{ {
unsigned char rgb = (((row & 0x8) == 0) ^ ((col & 0x8) == 0)) * 255; unsigned char rgb = ( ( ( row & 0x8 ) == 0 ) ^ ( ( col & 0x8 ) == 0 ) ) * 255;
pImageMemory[0] = rgb; pImageMemory[0] = rgb;
pImageMemory[1] = rgb; pImageMemory[1] = rgb;
pImageMemory[2] = rgb; pImageMemory[2] = rgb;
pImageMemory[3] = 255; pImageMemory[3] = 255;
pImageMemory += 4; pImageMemory += 4;
} }
} }
// Flush the mapped memory and then unmap it. Assume it isn't coherent since we didn't really confirm // Flush the mapped memory and then unmap it. Assume it isn't coherent since we didn't really confirm
device->flushMappedMemoryRanges(vk::MappedMemoryRange(deviceMemory.get(), 0, memoryRequirements.size)); device->flushMappedMemoryRanges( vk::MappedMemoryRange( deviceMemory.get(), 0, memoryRequirements.size ) );
device->unmapMemory(deviceMemory.get()); device->unmapMemory( deviceMemory.get() );
commandBuffer->reset({}); commandBuffer->reset( {} );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
// Intend to blit from this image, set the layout accordingly // Intend to blit from this image, set the layout accordingly
vk::su::setImageLayout(commandBuffer, blitSourceImage.get(), swapChainData.colorFormat, vk::ImageLayout::eGeneral, vk::ImageLayout::eTransferSrcOptimal); vk::su::setImageLayout( commandBuffer,
blitSourceImage.get(),
swapChainData.colorFormat,
vk::ImageLayout::eGeneral,
vk::ImageLayout::eTransferSrcOptimal );
vk::Image blitDestinationImage = swapChainData.images[currentBuffer]; vk::Image blitDestinationImage = swapChainData.images[currentBuffer];
// Do a 32x32 blit to all of the dst image - should get big squares // Do a 32x32 blit to all of the dst image - should get big squares
vk::ImageSubresourceLayers imageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1); vk::ImageSubresourceLayers imageSubresourceLayers( vk::ImageAspectFlagBits::eColor, 0, 0, 1 );
vk::ImageBlit imageBlit(imageSubresourceLayers, { { vk::Offset3D(0, 0, 0), vk::Offset3D(32, 32, 1) } }, imageSubresourceLayers, { { vk::Offset3D(0, 0, 0), vk::Offset3D(surfaceData.extent.width, surfaceData.extent.height, 1) } }); vk::ImageBlit imageBlit(
commandBuffer->blitImage(blitSourceImage.get(), vk::ImageLayout::eTransferSrcOptimal, blitDestinationImage, vk::ImageLayout::eTransferDstOptimal, imageBlit, vk::Filter::eLinear); imageSubresourceLayers,
{ { vk::Offset3D( 0, 0, 0 ), vk::Offset3D( 32, 32, 1 ) } },
imageSubresourceLayers,
{ { vk::Offset3D( 0, 0, 0 ), vk::Offset3D( surfaceData.extent.width, surfaceData.extent.height, 1 ) } } );
commandBuffer->blitImage( blitSourceImage.get(),
vk::ImageLayout::eTransferSrcOptimal,
blitDestinationImage,
vk::ImageLayout::eTransferDstOptimal,
imageBlit,
vk::Filter::eLinear );
// Use a barrier to make sure the blit is finished before the copy starts // Use a barrier to make sure the blit is finished before the copy starts
vk::ImageMemoryBarrier memoryBarrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eMemoryRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eTransferDstOptimal, vk::ImageMemoryBarrier memoryBarrier( vk::AccessFlagBits::eTransferWrite,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, blitDestinationImage, vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); vk::AccessFlagBits::eMemoryRead,
commandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlags(), nullptr, nullptr, memoryBarrier); vk::ImageLayout::eTransferDstOptimal,
vk::ImageLayout::eTransferDstOptimal,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
blitDestinationImage,
vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 ) );
commandBuffer->pipelineBarrier( vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eTransfer,
vk::DependencyFlags(),
nullptr,
nullptr,
memoryBarrier );
// Do a image copy to part of the dst image - checks should stay small // Do a image copy to part of the dst image - checks should stay small
vk::ImageCopy imageCopy(imageSubresourceLayers, vk::Offset3D(), imageSubresourceLayers, vk::Offset3D(256, 256, 0), vk::Extent3D(128, 128, 1)); vk::ImageCopy imageCopy( imageSubresourceLayers,
commandBuffer->copyImage(blitSourceImage.get(), vk::ImageLayout::eTransferSrcOptimal, blitDestinationImage, vk::ImageLayout::eTransferDstOptimal, imageCopy); vk::Offset3D(),
imageSubresourceLayers,
vk::Offset3D( 256, 256, 0 ),
vk::Extent3D( 128, 128, 1 ) );
commandBuffer->copyImage( blitSourceImage.get(),
vk::ImageLayout::eTransferSrcOptimal,
blitDestinationImage,
vk::ImageLayout::eTransferDstOptimal,
imageCopy );
vk::ImageMemoryBarrier prePresentBarrier(vk::AccessFlagBits::eTransferWrite, vk::AccessFlagBits::eMemoryRead, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::ePresentSrcKHR, vk::ImageMemoryBarrier prePresentBarrier(
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, swapChainData.images[currentBuffer], vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); vk::AccessFlagBits::eTransferWrite,
commandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eTopOfPipe, vk::DependencyFlags(), nullptr, nullptr, prePresentBarrier); vk::AccessFlagBits::eMemoryRead,
vk::ImageLayout::eTransferDstOptimal,
vk::ImageLayout::ePresentSrcKHR,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
swapChainData.images[currentBuffer],
vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 ) );
commandBuffer->pipelineBarrier( vk::PipelineStageFlagBits::eTransfer,
vk::PipelineStageFlagBits::eTopOfPipe,
vk::DependencyFlags(),
nullptr,
nullptr,
prePresentBarrier );
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique({}); vk::UniqueFence drawFence = device->createFenceUnique( {} );
graphicsQueue.submit(vk::SubmitInfo(0, nullptr, nullptr, 1, &commandBuffer.get()), drawFence.get()); graphicsQueue.submit( vk::SubmitInfo( 0, nullptr, nullptr, 1, &commandBuffer.get() ), drawFence.get() );
graphicsQueue.waitIdle(); graphicsQueue.waitIdle();
/* Make sure command buffer is finished before presenting */ /* Make sure command buffer is finished before presenting */
while (device->waitForFences(drawFence.get(), true, vk::su::FenceTimeout) == vk::Result::eTimeout) while ( device->waitForFences( drawFence.get(), true, vk::su::FenceTimeout ) == vk::Result::eTimeout )
; ;
/* Now present the image in the window */ /* Now present the image in the window */
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer, nullptr)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer, nullptr ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -16,68 +16,89 @@
// Draw a cube // Draw a cube
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
static char const* AppName = "CreateDebugReportMessenger"; static char const * AppName = "CreateDebugReportMessenger";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
PFN_vkCreateDebugUtilsMessengerEXT pfnVkCreateDebugUtilsMessengerEXT; PFN_vkCreateDebugUtilsMessengerEXT pfnVkCreateDebugUtilsMessengerEXT;
PFN_vkDestroyDebugUtilsMessengerEXT pfnVkDestroyDebugUtilsMessengerEXT; PFN_vkDestroyDebugUtilsMessengerEXT pfnVkDestroyDebugUtilsMessengerEXT;
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger) VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( VkInstance instance,
const VkDebugUtilsMessengerCreateInfoEXT * pCreateInfo,
const VkAllocationCallbacks * pAllocator,
VkDebugUtilsMessengerEXT * pMessenger )
{ {
return pfnVkCreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); return pfnVkCreateDebugUtilsMessengerEXT( instance, pCreateInfo, pAllocator, pMessenger );
} }
VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, VkAllocationCallbacks const * pAllocator) VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( VkInstance instance,
VkDebugUtilsMessengerEXT messenger,
VkAllocationCallbacks const * pAllocator )
{ {
return pfnVkDestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); return pfnVkDestroyDebugUtilsMessengerEXT( instance, messenger, pAllocator );
} }
VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageFunc( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageFunc(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
VkDebugUtilsMessengerCallbackDataEXT const * pCallbackData, void * /*pUserData*/) VkDebugUtilsMessengerCallbackDataEXT const * pCallbackData,
void * /*pUserData*/ )
{ {
std::ostringstream message; std::ostringstream message;
message << vk::to_string(static_cast<vk::DebugUtilsMessageSeverityFlagBitsEXT>(messageSeverity)) << ": " << vk::to_string(static_cast<vk::DebugUtilsMessageTypeFlagsEXT>(messageTypes)) << ":\n"; message << vk::to_string( static_cast<vk::DebugUtilsMessageSeverityFlagBitsEXT>( messageSeverity ) ) << ": "
message << "\t" << "messageIDName = <" << pCallbackData->pMessageIdName << ">\n"; << vk::to_string( static_cast<vk::DebugUtilsMessageTypeFlagsEXT>( messageTypes ) ) << ":\n";
message << "\t" << "messageIdNumber = " << pCallbackData->messageIdNumber << "\n"; message << "\t"
message << "\t" << "message = <" << pCallbackData->pMessage << ">\n"; << "messageIDName = <" << pCallbackData->pMessageIdName << ">\n";
if (0 < pCallbackData->queueLabelCount) message << "\t"
<< "messageIdNumber = " << pCallbackData->messageIdNumber << "\n";
message << "\t"
<< "message = <" << pCallbackData->pMessage << ">\n";
if ( 0 < pCallbackData->queueLabelCount )
{ {
message << "\t" << "Queue Labels:\n"; message << "\t"
for (uint8_t i = 0; i < pCallbackData->queueLabelCount; i++) << "Queue Labels:\n";
for ( uint8_t i = 0; i < pCallbackData->queueLabelCount; i++ )
{ {
message << "\t\t" << "labelName = <" << pCallbackData->pQueueLabels[i].pLabelName << ">\n"; message << "\t\t"
<< "labelName = <" << pCallbackData->pQueueLabels[i].pLabelName << ">\n";
} }
} }
if (0 < pCallbackData->cmdBufLabelCount) if ( 0 < pCallbackData->cmdBufLabelCount )
{ {
message << "\t" << "CommandBuffer Labels:\n"; message << "\t"
for (uint8_t i = 0; i < pCallbackData->cmdBufLabelCount; i++) << "CommandBuffer Labels:\n";
for ( uint8_t i = 0; i < pCallbackData->cmdBufLabelCount; i++ )
{ {
message << "\t\t" << "labelName = <" << pCallbackData->pCmdBufLabels[i].pLabelName << ">\n"; message << "\t\t"
<< "labelName = <" << pCallbackData->pCmdBufLabels[i].pLabelName << ">\n";
} }
} }
if (0 < pCallbackData->objectCount) if ( 0 < pCallbackData->objectCount )
{ {
message << "\t" << "Objects:\n"; message << "\t"
for (uint8_t i = 0; i < pCallbackData->objectCount; i++) << "Objects:\n";
for ( uint8_t i = 0; i < pCallbackData->objectCount; i++ )
{ {
message << "\t\t" << "Object " << i << "\n"; message << "\t\t"
message << "\t\t\t" << "objectType = " << vk::to_string(static_cast<vk::ObjectType>(pCallbackData->pObjects[i].objectType)) << "\n"; << "Object " << i << "\n";
message << "\t\t\t" << "objectHandle = " << pCallbackData->pObjects[i].objectHandle << "\n"; message << "\t\t\t"
if (pCallbackData->pObjects[i].pObjectName) << "objectType = "
<< vk::to_string( static_cast<vk::ObjectType>( pCallbackData->pObjects[i].objectType ) ) << "\n";
message << "\t\t\t"
<< "objectHandle = " << pCallbackData->pObjects[i].objectHandle << "\n";
if ( pCallbackData->pObjects[i].pObjectName )
{ {
message << "\t\t\t" << "objectName = <" << pCallbackData->pObjects[i].pObjectName << ">\n"; message << "\t\t\t"
<< "objectName = <" << pCallbackData->pObjects[i].pObjectName << ">\n";
} }
} }
} }
#ifdef _WIN32 #ifdef _WIN32
MessageBox(NULL, message.str().c_str(), "Alert", MB_OK); MessageBox( NULL, message.str().c_str(), "Alert", MB_OK );
#else #else
std::cout << message.str() << std::endl; std::cout << message.str() << std::endl;
#endif #endif
@ -85,8 +106,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageFunc(VkDebugUtilsMessageSeverityFlagB
return false; return false;
} }
int main( int /*argc*/, char ** /*argv*/ )
int main(int /*argc*/, char ** /*argv*/)
{ {
try try
{ {
@ -94,51 +114,61 @@ int main(int /*argc*/, char ** /*argv*/)
std::vector<vk::ExtensionProperties> props = vk::enumerateInstanceExtensionProperties(); std::vector<vk::ExtensionProperties> props = vk::enumerateInstanceExtensionProperties();
auto propsIterator = std::find_if(props.begin(), props.end(), [](vk::ExtensionProperties const& ep) { return strcmp(ep.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0; }); auto propsIterator = std::find_if( props.begin(), props.end(), []( vk::ExtensionProperties const & ep ) {
if (propsIterator == props.end()) return strcmp( ep.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME ) == 0;
} );
if ( propsIterator == props.end() )
{ {
std::cout << "Something went very wrong, cannot find " << VK_EXT_DEBUG_UTILS_EXTENSION_NAME << " extension" << std::endl; std::cout << "Something went very wrong, cannot find " << VK_EXT_DEBUG_UTILS_EXTENSION_NAME << " extension"
exit(1); << std::endl;
exit( 1 );
} }
vk::ApplicationInfo applicationInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1); vk::ApplicationInfo applicationInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
const char *extensionName = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; const char * extensionName = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo(vk::InstanceCreateFlags(), &applicationInfo, 0, nullptr, 1, &extensionName)); vk::UniqueInstance instance = vk::createInstanceUnique(
vk::InstanceCreateInfo( vk::InstanceCreateFlags(), &applicationInfo, 0, nullptr, 1, &extensionName ) );
pfnVkCreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(instance->getProcAddr("vkCreateDebugUtilsMessengerEXT")); pfnVkCreateDebugUtilsMessengerEXT =
if (!pfnVkCreateDebugUtilsMessengerEXT) reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>( instance->getProcAddr( "vkCreateDebugUtilsMessengerEXT" ) );
if ( !pfnVkCreateDebugUtilsMessengerEXT )
{ {
std::cout << "GetInstanceProcAddr: Unable to find pfnVkCreateDebugUtilsMessengerEXT function." << std::endl; std::cout << "GetInstanceProcAddr: Unable to find pfnVkCreateDebugUtilsMessengerEXT function." << std::endl;
exit(1); exit( 1 );
} }
pfnVkDestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(instance->getProcAddr("vkDestroyDebugUtilsMessengerEXT")); pfnVkDestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(
if (!pfnVkDestroyDebugUtilsMessengerEXT) instance->getProcAddr( "vkDestroyDebugUtilsMessengerEXT" ) );
if ( !pfnVkDestroyDebugUtilsMessengerEXT )
{ {
std::cout << "GetInstanceProcAddr: Unable to find pfnVkDestroyDebugUtilsMessengerEXT function." << std::endl; std::cout << "GetInstanceProcAddr: Unable to find pfnVkDestroyDebugUtilsMessengerEXT function." << std::endl;
exit(1); exit( 1 );
} }
vk::DebugUtilsMessageSeverityFlagsEXT severityFlags(vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError); vk::DebugUtilsMessageSeverityFlagsEXT severityFlags( vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags(vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation); vk::DebugUtilsMessageSeverityFlagBitsEXT::eError );
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = instance->createDebugUtilsMessengerEXTUnique(vk::DebugUtilsMessengerCreateInfoEXT({}, severityFlags, messageTypeFlags, &debugMessageFunc)); vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags( vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation );
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = instance->createDebugUtilsMessengerEXTUnique(
vk::DebugUtilsMessengerCreateInfoEXT( {}, severityFlags, messageTypeFlags, &debugMessageFunc ) );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,130 +19,186 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "DrawTexturedCube"; static char const * AppName = "DrawTexturedCube";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::TextureData textureData(physicalDevice, device); vk::su::TextureData textureData( physicalDevice, device );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
textureData.setImage(device, commandBuffer, vk::su::CheckerboardImageGenerator()); textureData.setImage( device, commandBuffer, vk::su::CheckerboardImageGenerator() );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
{ {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex}, {vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment} }); device,
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex },
{ vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, { {vk::DescriptorType::eUniformBuffer, 1}, {vk::DescriptorType::eCombinedImageSampler, 1} }); vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); device, { { vk::DescriptorType::eUniformBuffer, 1 }, { vk::DescriptorType::eCombinedImageSampler, 1 } } );
vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::su::updateDescriptorSets(device, descriptorSet, {{vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView()}}, textureData); vk::su::updateDescriptorSets(
device,
descriptorSet,
{ { vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView() } },
textureData );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline =
sizeof(texturedCubeData[0]), {{ vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 }}, vk::su::createGraphicsPipeline( device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( texturedCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
// commandBuffer->begin() has already been called above! // commandBuffer->begin() has already been called above!
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); framebuffers[currentBuffer.value].get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr); 2,
clearValues );
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,159 +19,231 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "DynamicUniform"; static char const * AppName = "DynamicUniform";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(coloredCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, coloredCubeData, sizeof(coloredCubeData) / sizeof(coloredCubeData[0])); physicalDevice, device, sizeof( coloredCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
coloredCubeData,
sizeof( coloredCubeData ) / sizeof( coloredCubeData[0] ) );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
vk::PhysicalDeviceLimits limits = physicalDevice.getProperties().limits; vk::PhysicalDeviceLimits limits = physicalDevice.getProperties().limits;
if (limits.maxDescriptorSetUniformBuffersDynamic < 1) if ( limits.maxDescriptorSetUniformBuffersDynamic < 1 )
{ {
std::cout << "No dynamic uniform buffers supported\n"; std::cout << "No dynamic uniform buffers supported\n";
exit(-1); exit( -1 );
} }
/* Set up uniform buffer with 2 transform matrices in it */ /* Set up uniform buffer with 2 transform matrices in it */
glm::mat4x4 mvpcs[2]; glm::mat4x4 mvpcs[2];
glm::mat4x4 model = glm::mat4x4(1.0f); glm::mat4x4 model = glm::mat4x4( 1.0f );
glm::mat4x4 view = glm::lookAt(glm::vec3(0.0f, 3.0f, -10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)); glm::mat4x4 view =
glm::mat4x4 projection = glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 100.0f); glm::lookAt( glm::vec3( 0.0f, 3.0f, -10.0f ), glm::vec3( 0.0f, 0.0f, 0.0f ), glm::vec3( 0.0f, -1.0f, 0.0f ) );
glm::mat4x4 clip = glm::mat4x4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f); // vulkan clip space has inverted y and half z ! glm::mat4x4 projection = glm::perspective( glm::radians( 45.0f ), 1.0f, 0.1f, 100.0f );
mvpcs[0] = clip * projection * view * model; glm::mat4x4 clip = glm::mat4x4( 1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
-1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
0.5f,
0.0f,
0.0f,
0.0f,
0.5f,
1.0f ); // vulkan clip space has inverted y and half z !
mvpcs[0] = clip * projection * view * model;
model = glm::translate(model, glm::vec3(-1.5f, 1.5f, -1.5f)); model = glm::translate( model, glm::vec3( -1.5f, 1.5f, -1.5f ) );
mvpcs[1] = clip * projection * view * model; mvpcs[1] = clip * projection * view * model;
vk::DeviceSize bufferSize = sizeof(glm::mat4x4); vk::DeviceSize bufferSize = sizeof( glm::mat4x4 );
if (limits.minUniformBufferOffsetAlignment) if ( limits.minUniformBufferOffsetAlignment )
{ {
bufferSize = (bufferSize + limits.minUniformBufferOffsetAlignment - 1) & ~(limits.minUniformBufferOffsetAlignment - 1); bufferSize =
( bufferSize + limits.minUniformBufferOffsetAlignment - 1 ) & ~( limits.minUniformBufferOffsetAlignment - 1 );
} }
vk::su::BufferData uniformBufferData(physicalDevice, device, 2 * bufferSize, vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, mvpcs, 2, bufferSize); physicalDevice, device, 2 * bufferSize, vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice( device, uniformBufferData.deviceMemory, mvpcs, 2, bufferSize );
// create a DescriptorSetLayout with vk::DescriptorType::eUniformBufferDynamic // create a DescriptorSetLayout with vk::DescriptorType::eUniformBufferDynamic
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, { {vk::DescriptorType::eUniformBufferDynamic, 1, vk::ShaderStageFlagBits::eVertex} }); vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); device, { { vk::DescriptorType::eUniformBufferDynamic, 1, vk::ShaderStageFlagBits::eVertex } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
// create a DescriptorPool with vk::DescriptorType::eUniformBufferDynamic // create a DescriptorPool with vk::DescriptorType::eUniformBufferDynamic
vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, { { vk::DescriptorType::eUniformBufferDynamic, 1 } }); vk::UniqueDescriptorPool descriptorPool =
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); vk::su::createDescriptorPool( device, { { vk::DescriptorType::eUniformBufferDynamic, 1 } } );
vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::su::updateDescriptorSets(device, descriptorSet, {{vk::DescriptorType::eUniformBufferDynamic, uniformBufferData.buffer, vk::UniqueBufferView()}}, {}); vk::su::updateDescriptorSets(
device,
descriptorSet,
{ { vk::DescriptorType::eUniformBufferDynamic, uniformBufferData.buffer, vk::UniqueBufferView() } },
{} );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(
sizeof(coloredCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32B32A32Sfloat, 16 } }, device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( coloredCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32B32A32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); commandBuffer->begin( vk::CommandBufferBeginInfo( vk::CommandBufferUsageFlags() ) );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); framebuffers[currentBuffer.value].get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
2,
clearValues );
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
/* The first draw should use the first matrix in the buffer */ /* The first draw should use the first matrix in the buffer */
uint32_t dynamicOffset = 0; uint32_t dynamicOffset = 0;
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), dynamicOffset); commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), dynamicOffset );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
// the second draw should use the second matrix in the buffer; // the second draw should use the second matrix in the buffer;
dynamicOffset = (uint32_t)bufferSize; dynamicOffset = (uint32_t)bufferSize;
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), dynamicOffset); commandBuffer->bindDescriptorSets(
commandBuffer->draw(12 * 3, 1, 0, 0); vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), dynamicOffset );
commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,68 +17,78 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
static char const* AppName = "EnableValidationWithCallback"; static char const * AppName = "EnableValidationWithCallback";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
PFN_vkCreateDebugUtilsMessengerEXT pfnVkCreateDebugUtilsMessengerEXT; PFN_vkCreateDebugUtilsMessengerEXT pfnVkCreateDebugUtilsMessengerEXT;
PFN_vkDestroyDebugUtilsMessengerEXT pfnVkDestroyDebugUtilsMessengerEXT; PFN_vkDestroyDebugUtilsMessengerEXT pfnVkDestroyDebugUtilsMessengerEXT;
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger) VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugUtilsMessengerEXT( VkInstance instance,
const VkDebugUtilsMessengerCreateInfoEXT * pCreateInfo,
const VkAllocationCallbacks * pAllocator,
VkDebugUtilsMessengerEXT * pMessenger )
{ {
return pfnVkCreateDebugUtilsMessengerEXT(instance, pCreateInfo, pAllocator, pMessenger); return pfnVkCreateDebugUtilsMessengerEXT( instance, pCreateInfo, pAllocator, pMessenger );
} }
VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger, VkAllocationCallbacks const * pAllocator) VKAPI_ATTR void VKAPI_CALL vkDestroyDebugUtilsMessengerEXT( VkInstance instance,
VkDebugUtilsMessengerEXT messenger,
VkAllocationCallbacks const * pAllocator )
{ {
return pfnVkDestroyDebugUtilsMessengerEXT(instance, messenger, pAllocator); return pfnVkDestroyDebugUtilsMessengerEXT( instance, messenger, pAllocator );
} }
VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageFunc( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageFunc(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
VkDebugUtilsMessengerCallbackDataEXT const * pCallbackData, void * /*pUserData*/) VkDebugUtilsMessengerCallbackDataEXT const * pCallbackData,
void * /*pUserData*/ )
{ {
std::string message; std::string message;
message += vk::to_string(static_cast<vk::DebugUtilsMessageSeverityFlagBitsEXT>(messageSeverity)) + ": " + vk::to_string(static_cast<vk::DebugUtilsMessageTypeFlagsEXT>(messageTypes)) + ":\n"; message += vk::to_string( static_cast<vk::DebugUtilsMessageSeverityFlagBitsEXT>( messageSeverity ) ) + ": " +
message += std::string("\t") + "messageIDName = <" + pCallbackData->pMessageIdName + ">\n"; vk::to_string( static_cast<vk::DebugUtilsMessageTypeFlagsEXT>( messageTypes ) ) + ":\n";
message += std::string("\t") + "messageIdNumber = " + std::to_string(pCallbackData->messageIdNumber) + "\n"; message += std::string( "\t" ) + "messageIDName = <" + pCallbackData->pMessageIdName + ">\n";
message += std::string("\t") + "message = <" + pCallbackData->pMessage + ">\n"; message += std::string( "\t" ) + "messageIdNumber = " + std::to_string( pCallbackData->messageIdNumber ) + "\n";
if (0 < pCallbackData->queueLabelCount) message += std::string( "\t" ) + "message = <" + pCallbackData->pMessage + ">\n";
if ( 0 < pCallbackData->queueLabelCount )
{ {
message += std::string("\t") + "Queue Labels:\n"; message += std::string( "\t" ) + "Queue Labels:\n";
for (uint8_t i = 0; i < pCallbackData->queueLabelCount; i++) for ( uint8_t i = 0; i < pCallbackData->queueLabelCount; i++ )
{ {
message += std::string("\t\t") + "labelName = <" + pCallbackData->pQueueLabels[i].pLabelName + ">\n"; message += std::string( "\t\t" ) + "labelName = <" + pCallbackData->pQueueLabels[i].pLabelName + ">\n";
} }
} }
if (0 < pCallbackData->cmdBufLabelCount) if ( 0 < pCallbackData->cmdBufLabelCount )
{ {
message += std::string("\t") + "CommandBuffer Labels:\n"; message += std::string( "\t" ) + "CommandBuffer Labels:\n";
for (uint8_t i = 0; i < pCallbackData->cmdBufLabelCount; i++) for ( uint8_t i = 0; i < pCallbackData->cmdBufLabelCount; i++ )
{ {
message += std::string("\t\t") + "labelName = <" + pCallbackData->pCmdBufLabels[i].pLabelName + ">\n"; message += std::string( "\t\t" ) + "labelName = <" + pCallbackData->pCmdBufLabels[i].pLabelName + ">\n";
} }
} }
if (0 < pCallbackData->objectCount) if ( 0 < pCallbackData->objectCount )
{ {
for (uint8_t i = 0; i < pCallbackData->objectCount; i++) for ( uint8_t i = 0; i < pCallbackData->objectCount; i++ )
{ {
message += std::string("\t") + "Object " + std::to_string(i) + "\n"; message += std::string( "\t" ) + "Object " + std::to_string( i ) + "\n";
message += std::string("\t\t") + "objectType = " + vk::to_string(static_cast<vk::ObjectType>(pCallbackData->pObjects[i].objectType)) + "\n"; message += std::string( "\t\t" ) + "objectType = " +
message += std::string("\t\t") + "objectHandle = " + std::to_string(pCallbackData->pObjects[i].objectHandle) + "\n"; vk::to_string( static_cast<vk::ObjectType>( pCallbackData->pObjects[i].objectType ) ) + "\n";
if (pCallbackData->pObjects[i].pObjectName) message +=
std::string( "\t\t" ) + "objectHandle = " + std::to_string( pCallbackData->pObjects[i].objectHandle ) + "\n";
if ( pCallbackData->pObjects[i].pObjectName )
{ {
message += std::string("\t\t") + "objectName = <" + pCallbackData->pObjects[i].pObjectName + ">\n"; message += std::string( "\t\t" ) + "objectName = <" + pCallbackData->pObjects[i].pObjectName + ">\n";
} }
}
} }
}
#ifdef _WIN32 #ifdef _WIN32
MessageBox(NULL, message.c_str(), "Alert", MB_OK); MessageBox( NULL, message.c_str(), "Alert", MB_OK );
#else #else
std::cout << message << std::endl; std::cout << message << std::endl;
#endif #endif
@ -86,24 +96,26 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageFunc(VkDebugUtilsMessageSeverityFlagB
return false; return false;
} }
bool checkLayers(std::vector<char const*> const& layers, std::vector<vk::LayerProperties> const& properties) bool checkLayers( std::vector<char const *> const & layers, std::vector<vk::LayerProperties> const & properties )
{ {
// return true if all layers are listed in the properties // return true if all layers are listed in the properties
return std::all_of(layers.begin(), layers.end(), [&properties](char const* name) return std::all_of( layers.begin(), layers.end(), [&properties]( char const * name ) {
{ return std::find_if( properties.begin(), properties.end(), [&name]( vk::LayerProperties const & property ) {
return std::find_if(properties.begin(), properties.end(), [&name](vk::LayerProperties const& property) { return strcmp(property.layerName, name) == 0; }) != properties.end(); return strcmp( property.layerName, name ) == 0;
}); } ) != properties.end();
} );
} }
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
#if (VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1) #if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
// initialize the DipatchLoaderDynamic to use // initialize the DipatchLoaderDynamic to use
static vk::DynamicLoader dl; static vk::DynamicLoader dl;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); dl.getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" );
VULKAN_HPP_DEFAULT_DISPATCHER.init( vkGetInstanceProcAddr );
#endif #endif
std::vector<vk::LayerProperties> instanceLayerProperties = vk::enumerateInstanceLayerProperties(); std::vector<vk::LayerProperties> instanceLayerProperties = vk::enumerateInstanceLayerProperties();
@ -111,61 +123,77 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Use standard_validation meta layer that enables all recommended validation layers // Use standard_validation meta layer that enables all recommended validation layers
std::vector<char const*> instanceLayerNames; std::vector<char const *> instanceLayerNames;
instanceLayerNames.push_back("VK_LAYER_KHRONOS_validation"); instanceLayerNames.push_back( "VK_LAYER_KHRONOS_validation" );
if (!checkLayers(instanceLayerNames, instanceLayerProperties)) if ( !checkLayers( instanceLayerNames, instanceLayerProperties ) )
{ {
std::cout << "Set the environment variable VK_LAYER_PATH to point to the location of your layers" << std::endl; std::cout << "Set the environment variable VK_LAYER_PATH to point to the location of your layers" << std::endl;
exit(1); exit( 1 );
} }
/* Enable debug callback extension */ /* Enable debug callback extension */
std::vector<char const*> instanceExtensionNames; std::vector<char const *> instanceExtensionNames;
instanceExtensionNames.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); instanceExtensionNames.push_back( VK_EXT_DEBUG_UTILS_EXTENSION_NAME );
vk::ApplicationInfo applicationInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1); vk::ApplicationInfo applicationInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
vk::InstanceCreateInfo instanceCreateInfo( vk::InstanceCreateFlags(), &applicationInfo, vk::su::checked_cast<uint32_t>(instanceLayerNames.size()), instanceLayerNames.data(), vk::InstanceCreateInfo instanceCreateInfo( vk::InstanceCreateFlags(),
vk::su::checked_cast<uint32_t>(instanceExtensionNames.size()) , instanceExtensionNames.data() ); &applicationInfo,
vk::UniqueInstance instance = vk::createInstanceUnique(instanceCreateInfo); vk::su::checked_cast<uint32_t>( instanceLayerNames.size() ),
instanceLayerNames.data(),
vk::su::checked_cast<uint32_t>( instanceExtensionNames.size() ),
instanceExtensionNames.data() );
vk::UniqueInstance instance = vk::createInstanceUnique( instanceCreateInfo );
#if (VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1) #if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
// initialize function pointers for instance // initialize function pointers for instance
VULKAN_HPP_DEFAULT_DISPATCHER.init(*instance); VULKAN_HPP_DEFAULT_DISPATCHER.init( *instance );
#endif #endif
pfnVkCreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(instance->getProcAddr("vkCreateDebugUtilsMessengerEXT")); pfnVkCreateDebugUtilsMessengerEXT =
if (!pfnVkCreateDebugUtilsMessengerEXT) reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>( instance->getProcAddr( "vkCreateDebugUtilsMessengerEXT" ) );
if ( !pfnVkCreateDebugUtilsMessengerEXT )
{ {
std::cout << "GetInstanceProcAddr: Unable to find pfnVkCreateDebugUtilsMessengerEXT function." << std::endl; std::cout << "GetInstanceProcAddr: Unable to find pfnVkCreateDebugUtilsMessengerEXT function." << std::endl;
exit(1); exit( 1 );
} }
pfnVkDestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(instance->getProcAddr("vkDestroyDebugUtilsMessengerEXT")); pfnVkDestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(
if (!pfnVkDestroyDebugUtilsMessengerEXT) instance->getProcAddr( "vkDestroyDebugUtilsMessengerEXT" ) );
if ( !pfnVkDestroyDebugUtilsMessengerEXT )
{ {
std::cout << "GetInstanceProcAddr: Unable to find pfnVkDestroyDebugUtilsMessengerEXT function." << std::endl; std::cout << "GetInstanceProcAddr: Unable to find pfnVkDestroyDebugUtilsMessengerEXT function." << std::endl;
exit(1); exit( 1 );
} }
vk::DebugUtilsMessageSeverityFlagsEXT severityFlags(vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | vk::DebugUtilsMessageSeverityFlagBitsEXT::eError); vk::DebugUtilsMessageSeverityFlagsEXT severityFlags( vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags(vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance | vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation); vk::DebugUtilsMessageSeverityFlagBitsEXT::eError );
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = instance->createDebugUtilsMessengerEXTUnique(vk::DebugUtilsMessengerCreateInfoEXT({}, severityFlags, messageTypeFlags, &debugMessageFunc)); vk::DebugUtilsMessageTypeFlagsEXT messageTypeFlags( vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance |
vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation );
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = instance->createDebugUtilsMessengerEXTUnique(
vk::DebugUtilsMessengerCreateInfoEXT( {}, severityFlags, messageTypeFlags, &debugMessageFunc ) );
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties(); std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
assert(!queueFamilyProperties.empty()); assert( !queueFamilyProperties.empty() );
auto qfpIt = std::find_if(queueFamilyProperties.begin(), queueFamilyProperties.end(), [](vk::QueueFamilyProperties const& qfp) { return !!(qfp.queueFlags & vk::QueueFlagBits::eGraphics); }); auto qfpIt = std::find_if(
assert(qfpIt != queueFamilyProperties.end()); queueFamilyProperties.begin(), queueFamilyProperties.end(), []( vk::QueueFamilyProperties const & qfp ) {
uint32_t queueFamilyIndex = static_cast<uint32_t>(std::distance(queueFamilyProperties.begin(), qfpIt)); return !!( qfp.queueFlags & vk::QueueFlagBits::eGraphics );
} );
assert( qfpIt != queueFamilyProperties.end() );
uint32_t queueFamilyIndex = static_cast<uint32_t>( std::distance( queueFamilyProperties.begin(), qfpIt ) );
float queuePriority = 0.0f; float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), queueFamilyIndex, 1, &queuePriority); vk::DeviceQueueCreateInfo deviceQueueCreateInfo(
vk::UniqueDevice device = physicalDevice.createDeviceUnique(vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo)); vk::DeviceQueueCreateFlags(), queueFamilyIndex, 1, &queuePriority );
vk::UniqueDevice device =
physicalDevice.createDeviceUnique( vk::DeviceCreateInfo( vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo ) );
// Create a command pool (not a UniqueCommandPool, for testing purposes! // Create a command pool (not a UniqueCommandPool, for testing purposes!
vk::CommandPool commandPool = device->createCommandPool(vk::CommandPoolCreateInfo(vk::CommandPoolCreateFlags(), queueFamilyIndex)); vk::CommandPool commandPool =
device->createCommandPool( vk::CommandPoolCreateInfo( vk::CommandPoolCreateFlags(), queueFamilyIndex ) );
// The commandPool is not destroyed automatically (as it's not a UniqueCommandPool. // The commandPool is not destroyed automatically (as it's not a UniqueCommandPool.
// That is, the device is destroyed before the commmand pool and will trigger a validation error. // That is, the device is destroyed before the commmand pool and will trigger a validation error.
@ -174,20 +202,20 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,19 +17,20 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
static char const* AppName = "EnumerateDevicesAdvanced"; static char const * AppName = "EnumerateDevicesAdvanced";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
/* VULKAN_HPP_KEY_START */ /* VULKAN_HPP_KEY_START */
@ -37,41 +38,41 @@ int main(int /*argc*/, char ** /*argv*/)
// enumerate the physicalDevices // enumerate the physicalDevices
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices(); std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
for (auto const& physicalDevice : physicalDevices) for ( auto const & physicalDevice : physicalDevices )
{ {
vk::PhysicalDeviceProperties properties = physicalDevice.getProperties(); vk::PhysicalDeviceProperties properties = physicalDevice.getProperties();
std::cout << "apiVersion: "; std::cout << "apiVersion: ";
std::cout << ((properties.apiVersion >> 22) & 0xfff) << '.'; // Major. std::cout << ( ( properties.apiVersion >> 22 ) & 0xfff ) << '.'; // Major.
std::cout << ((properties.apiVersion >> 12) & 0x3ff) << '.'; // Minor. std::cout << ( ( properties.apiVersion >> 12 ) & 0x3ff ) << '.'; // Minor.
std::cout << (properties.apiVersion & 0xfff); // Patch. std::cout << ( properties.apiVersion & 0xfff ); // Patch.
std::cout << '\n'; std::cout << '\n';
std::cout << "driverVersion: " << properties.driverVersion << '\n'; std::cout << "driverVersion: " << properties.driverVersion << '\n';
std::cout << std::showbase << std::internal << std::setfill('0') << std::hex; std::cout << std::showbase << std::internal << std::setfill( '0' ) << std::hex;
std::cout << "vendorId: " << std::setw(6) << properties.vendorID << '\n'; std::cout << "vendorId: " << std::setw( 6 ) << properties.vendorID << '\n';
std::cout << "deviceId: " << std::setw(6) << properties.deviceID << '\n'; std::cout << "deviceId: " << std::setw( 6 ) << properties.deviceID << '\n';
std::cout << std::noshowbase << std::right << std::setfill(' ') << std::dec; std::cout << std::noshowbase << std::right << std::setfill( ' ' ) << std::dec;
std::cout << "deviceType: " << vk::to_string(properties.deviceType) << "\n"; std::cout << "deviceType: " << vk::to_string( properties.deviceType ) << "\n";
std::cout << "deviceName: " << properties.deviceName << '\n'; std::cout << "deviceName: " << properties.deviceName << '\n';
std::cout << "pipelineCacheUUID: " << vk::su::UUID(properties.pipelineCacheUUID) << "\n\n"; std::cout << "pipelineCacheUUID: " << vk::su::UUID( properties.pipelineCacheUUID ) << "\n\n";
} }
/* VULKAN_HPP_KEY_END */ /* VULKAN_HPP_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,135 +17,145 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "Events"; static char const * AppName = "Events";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
uint32_t graphicsQueueFamilyIndex = vk::su::findGraphicsQueueFamilyIndex(physicalDevice.getQueueFamilyProperties()); uint32_t graphicsQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsQueueFamilyIndex); vk::su::findGraphicsQueueFamilyIndex( physicalDevice.getQueueFamilyProperties() );
vk::UniqueDevice device = vk::su::createDevice( physicalDevice, graphicsQueueFamilyIndex );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsQueueFamilyIndex); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsQueueFamilyIndex );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsQueueFamilyIndex, 0); vk::Queue graphicsQueue = device->getQueue( graphicsQueueFamilyIndex, 0 );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Start with a trivial command buffer and make sure fence wait doesn't time out // Start with a trivial command buffer and make sure fence wait doesn't time out
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); commandBuffer->begin( vk::CommandBufferBeginInfo( vk::CommandBufferUsageFlags() ) );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, 10.0f, 10.0f, 0.0f, 1.0f)); commandBuffer->setViewport( 0, vk::Viewport( 0.0f, 0.0f, 10.0f, 10.0f, 0.0f, 1.0f ) );
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence fence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence fence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(0, nullptr, &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 0, nullptr, &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, fence.get()); graphicsQueue.submit( submitInfo, fence.get() );
// Make sure timeout is long enough for a simple command buffer without waiting for an event // Make sure timeout is long enough for a simple command buffer without waiting for an event
vk::Result result; vk::Result result;
int timeouts = -1; int timeouts = -1;
do do
{ {
result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout); result = device->waitForFences( fence.get(), true, vk::su::FenceTimeout );
timeouts++; timeouts++;
} while (result == vk::Result::eTimeout); } while ( result == vk::Result::eTimeout );
assert(result == vk::Result::eSuccess); assert( result == vk::Result::eSuccess );
if (timeouts != 0) if ( timeouts != 0 )
{ {
std::cout << "Unsuitable timeout value, exiting\n"; std::cout << "Unsuitable timeout value, exiting\n";
exit(-1); exit( -1 );
} }
// Now create an event and wait for it on the GPU // Now create an event and wait for it on the GPU
vk::UniqueEvent event = device->createEventUnique(vk::EventCreateInfo(vk::EventCreateFlags())); vk::UniqueEvent event = device->createEventUnique( vk::EventCreateInfo( vk::EventCreateFlags() ) );
commandBuffer->reset(vk::CommandBufferResetFlags()); commandBuffer->reset( vk::CommandBufferResetFlags() );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
commandBuffer->waitEvents(event.get(), vk::PipelineStageFlagBits::eHost, vk::PipelineStageFlagBits::eBottomOfPipe, nullptr, nullptr, nullptr); commandBuffer->waitEvents( event.get(),
vk::PipelineStageFlagBits::eHost,
vk::PipelineStageFlagBits::eBottomOfPipe,
nullptr,
nullptr,
nullptr );
commandBuffer->end(); commandBuffer->end();
device->resetFences(fence.get()); device->resetFences( fence.get() );
// Note that stepping through this code in the debugger is a bad idea because the GPU can TDR waiting for the event. // Note that stepping through this code in the debugger is a bad idea because the GPU can TDR waiting for the event.
// Execute the code from vk::Queue::submit() through vk::Device::setEvent() without breakpoints // Execute the code from vk::Queue::submit() through vk::Device::setEvent() without breakpoints
waitDestinationStageMask = vk::PipelineStageFlagBits::eBottomOfPipe; waitDestinationStageMask = vk::PipelineStageFlagBits::eBottomOfPipe;
graphicsQueue.submit(submitInfo, fence.get()); graphicsQueue.submit( submitInfo, fence.get() );
// We should timeout waiting for the fence because the GPU should be waiting on the event // We should timeout waiting for the fence because the GPU should be waiting on the event
result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout); result = device->waitForFences( fence.get(), true, vk::su::FenceTimeout );
if (result != vk::Result::eTimeout) if ( result != vk::Result::eTimeout )
{ {
std::cout << "Didn't get expected timeout in vk::Device::waitForFences, exiting\n"; std::cout << "Didn't get expected timeout in vk::Device::waitForFences, exiting\n";
exit(-1); exit( -1 );
} }
// Set the event from the CPU and wait for the fence. // Set the event from the CPU and wait for the fence.
// This should succeed since we set the event // This should succeed since we set the event
device->setEvent(event.get()); device->setEvent( event.get() );
do do
{ {
result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout); result = device->waitForFences( fence.get(), true, vk::su::FenceTimeout );
} while (result == vk::Result::eTimeout); } while ( result == vk::Result::eTimeout );
assert(result == vk::Result::eSuccess); assert( result == vk::Result::eSuccess );
commandBuffer->reset({}); commandBuffer->reset( {} );
device->resetFences(fence.get()); device->resetFences( fence.get() );
device->resetEvent(event.get()); device->resetEvent( event.get() );
// Now set the event from the GPU and wait on the CPU // Now set the event from the GPU and wait on the CPU
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
commandBuffer->setEvent(event.get(), vk::PipelineStageFlagBits::eBottomOfPipe); commandBuffer->setEvent( event.get(), vk::PipelineStageFlagBits::eBottomOfPipe );
commandBuffer->end(); commandBuffer->end();
// Look for the event on the CPU. It should be vk::Result::eEventReset since we haven't sent the command buffer yet. // Look for the event on the CPU. It should be vk::Result::eEventReset since we haven't sent the command buffer yet.
result = device->getEventStatus(event.get()); result = device->getEventStatus( event.get() );
assert(result == vk::Result::eEventReset); assert( result == vk::Result::eEventReset );
// Send the command buffer and loop waiting for the event // Send the command buffer and loop waiting for the event
graphicsQueue.submit(submitInfo, fence.get()); graphicsQueue.submit( submitInfo, fence.get() );
int polls = 0; int polls = 0;
do do
{ {
result = device->getEventStatus(event.get()); result = device->getEventStatus( event.get() );
polls++; polls++;
} while (result != vk::Result::eEventSet); } while ( result != vk::Result::eEventSet );
printf("%d polls to find the event set\n", polls); printf( "%d polls to find the event set\n", polls );
do do
{ {
result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout); result = device->waitForFences( fence.get(), true, vk::su::FenceTimeout );
} while (result == vk::Result::eTimeout); } while ( result == vk::Result::eTimeout );
assert(result == vk::Result::eSuccess); assert( result == vk::Result::eSuccess );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,142 +19,194 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "ImmutableSampler"; static char const * AppName = "ImmutableSampler";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
vk::su::TextureData textureData(physicalDevice, device); vk::su::TextureData textureData( physicalDevice, device );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
textureData.setImage(device, commandBuffer, vk::su::CheckerboardImageGenerator()); textureData.setImage( device, commandBuffer, vk::su::CheckerboardImageGenerator() );
vk::DescriptorSetLayoutBinding bindings[2] = vk::DescriptorSetLayoutBinding bindings[2] = {
{ vk::DescriptorSetLayoutBinding( 0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex ),
vk::DescriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex), vk::DescriptorSetLayoutBinding( 1,
vk::DescriptorSetLayoutBinding(1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment, &textureData.textureSampler.get()) vk::DescriptorType::eCombinedImageSampler,
1,
vk::ShaderStageFlagBits::eFragment,
&textureData.textureSampler.get() )
}; };
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), 2, bindings)); vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(
vk::DescriptorSetLayoutCreateInfo( vk::DescriptorSetLayoutCreateFlags(), 2, bindings ) );
// Create pipeline layout // Create pipeline layout
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
// Create a single pool to contain data for our descriptor set // Create a single pool to contain data for our descriptor set
vk::DescriptorPoolSize poolSizes[2] = vk::DescriptorPoolSize poolSizes[2] = { vk::DescriptorPoolSize( vk::DescriptorType::eUniformBuffer, 1 ),
{ vk::DescriptorPoolSize( vk::DescriptorType::eCombinedImageSampler, 1 ) };
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1), vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(
vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, 1) vk::DescriptorPoolCreateInfo( vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 2, poolSizes ) );
};
vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 2, poolSizes));
// Populate descriptor sets // Populate descriptor sets
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::DescriptorBufferInfo bufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); vk::DescriptorBufferInfo bufferInfo( uniformBufferData.buffer.get(), 0, sizeof( glm::mat4x4 ) );
vk::DescriptorImageInfo imageInfo(textureData.textureSampler.get(), textureData.imageData->imageView.get(), vk::ImageLayout::eShaderReadOnlyOptimal); vk::DescriptorImageInfo imageInfo( textureData.textureSampler.get(),
vk::WriteDescriptorSet writeDescriptorSets[2] = textureData.imageData->imageView.get(),
{ vk::ImageLayout::eShaderReadOnlyOptimal );
vk::WriteDescriptorSet(descriptorSet.get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo), vk::WriteDescriptorSet writeDescriptorSets[2] = {
vk::WriteDescriptorSet(descriptorSet.get(), 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo) vk::WriteDescriptorSet( descriptorSet.get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo ),
vk::WriteDescriptorSet( descriptorSet.get(), 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo )
}; };
device->updateDescriptorSets(vk::ArrayProxy<const vk::WriteDescriptorSet>(2, writeDescriptorSets), nullptr); device->updateDescriptorSets( vk::ArrayProxy<const vk::WriteDescriptorSet>( 2, writeDescriptorSets ), nullptr );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline =
sizeof(texturedCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } }, vk::su::createGraphicsPipeline( device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( texturedCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); framebuffers[currentBuffer.value].get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr); 2,
clearValues );
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::su::submitAndWait(device, graphicsQueue, commandBuffer); vk::su::submitAndWait( device, graphicsQueue, commandBuffer );
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,141 +19,203 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "InitTexture"; static char const * AppName = "InitTexture";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(50, 50)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 50, 50 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
vk::Format format = vk::Format::eR8G8B8A8Unorm; vk::Format format = vk::Format::eR8G8B8A8Unorm;
vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(format); vk::FormatProperties formatProperties = physicalDevice.getFormatProperties( format );
// See if we can use a linear tiled image for a texture, if not, we will need a staging buffer for the texture data // See if we can use a linear tiled image for a texture, if not, we will need a staging buffer for the texture data
bool needsStaging = !(formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eSampledImage); bool needsStaging = !( formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eSampledImage );
vk::UniqueImage image = device->createImageUnique(vk::ImageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, format, vk::Extent3D(surfaceData.extent, 1), 1, 1, vk::UniqueImage image = device->createImageUnique(
vk::SampleCountFlagBits::e1, needsStaging ? vk::ImageTiling::eOptimal : vk::ImageTiling::eLinear, vk::ImageCreateInfo( vk::ImageCreateFlags(),
vk::ImageUsageFlagBits::eSampled | (needsStaging ? vk::ImageUsageFlagBits::eTransferDst : vk::ImageUsageFlagBits()), vk::ImageType::e2D,
vk::SharingMode::eExclusive, 0, nullptr, needsStaging ? vk::ImageLayout::eUndefined : vk::ImageLayout::ePreinitialized)); format,
vk::Extent3D( surfaceData.extent, 1 ),
1,
1,
vk::SampleCountFlagBits::e1,
needsStaging ? vk::ImageTiling::eOptimal : vk::ImageTiling::eLinear,
vk::ImageUsageFlagBits::eSampled |
( needsStaging ? vk::ImageUsageFlagBits::eTransferDst : vk::ImageUsageFlagBits() ),
vk::SharingMode::eExclusive,
0,
nullptr,
needsStaging ? vk::ImageLayout::eUndefined : vk::ImageLayout::ePreinitialized ) );
vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements(image.get()); vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements( image.get() );
uint32_t memoryTypeIndex = vk::su::findMemoryType(physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, uint32_t memoryTypeIndex = vk::su::findMemoryType(
needsStaging ? vk::MemoryPropertyFlags() : (vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent)); physicalDevice.getMemoryProperties(),
memoryRequirements.memoryTypeBits,
needsStaging ? vk::MemoryPropertyFlags()
: ( vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent ) );
// allocate memory // allocate memory
vk::UniqueDeviceMemory imageMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); vk::UniqueDeviceMemory imageMemory =
device->allocateMemoryUnique( vk::MemoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ) );
// bind memory // bind memory
device->bindImageMemory(image.get(), imageMemory.get(), 0); device->bindImageMemory( image.get(), imageMemory.get(), 0 );
vk::UniqueBuffer textureBuffer; vk::UniqueBuffer textureBuffer;
vk::UniqueDeviceMemory textureBufferMemory; vk::UniqueDeviceMemory textureBufferMemory;
if (needsStaging) if ( needsStaging )
{ {
// Need a staging buffer to map and copy texture into // Need a staging buffer to map and copy texture into
textureBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), surfaceData.extent.width * surfaceData.extent.height * 4, vk::BufferUsageFlagBits::eTransferSrc)); textureBuffer =
device->createBufferUnique( vk::BufferCreateInfo( vk::BufferCreateFlags(),
surfaceData.extent.width * surfaceData.extent.height * 4,
vk::BufferUsageFlagBits::eTransferSrc ) );
memoryRequirements = device->getBufferMemoryRequirements(textureBuffer.get()); memoryRequirements = device->getBufferMemoryRequirements( textureBuffer.get() );
memoryTypeIndex = vk::su::findMemoryType(physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); memoryTypeIndex =
vk::su::findMemoryType( physicalDevice.getMemoryProperties(),
memoryRequirements.memoryTypeBits,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent );
// allocate memory // allocate memory
textureBufferMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); textureBufferMemory =
device->allocateMemoryUnique( vk::MemoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ) );
// bind memory // bind memory
device->bindBufferMemory(textureBuffer.get(), textureBufferMemory.get(), 0); device->bindBufferMemory( textureBuffer.get(), textureBufferMemory.get(), 0 );
} }
else else
{ {
vk::SubresourceLayout subresourceLayout = device->getImageSubresourceLayout(image.get(), vk::ImageSubresource(vk::ImageAspectFlagBits::eColor)); vk::SubresourceLayout subresourceLayout =
device->getImageSubresourceLayout( image.get(), vk::ImageSubresource( vk::ImageAspectFlagBits::eColor ) );
} }
void* data = device->mapMemory(needsStaging ? textureBufferMemory.get() : imageMemory.get(), 0, memoryRequirements.size, vk::MemoryMapFlags()); void * data = device->mapMemory(
needsStaging ? textureBufferMemory.get() : imageMemory.get(), 0, memoryRequirements.size, vk::MemoryMapFlags() );
// Checkerboard of 16x16 pixel squares // Checkerboard of 16x16 pixel squares
unsigned char *pImageMemory = static_cast<unsigned char*>(data); unsigned char * pImageMemory = static_cast<unsigned char *>( data );
for (uint32_t row = 0; row < surfaceData.extent.height; row++) for ( uint32_t row = 0; row < surfaceData.extent.height; row++ )
{ {
for (uint32_t col = 0; col < surfaceData.extent.width; col++) for ( uint32_t col = 0; col < surfaceData.extent.width; col++ )
{ {
unsigned char rgb = (((row & 0x10) == 0) ^ ((col & 0x10) == 0)) * 255; unsigned char rgb = ( ( ( row & 0x10 ) == 0 ) ^ ( ( col & 0x10 ) == 0 ) ) * 255;
pImageMemory[0] = rgb; pImageMemory[0] = rgb;
pImageMemory[1] = rgb; pImageMemory[1] = rgb;
pImageMemory[2] = rgb; pImageMemory[2] = rgb;
pImageMemory[3] = 255; pImageMemory[3] = 255;
pImageMemory += 4; pImageMemory += 4;
} }
} }
device->unmapMemory(needsStaging ? textureBufferMemory.get() : imageMemory.get()); device->unmapMemory( needsStaging ? textureBufferMemory.get() : imageMemory.get() );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
if (needsStaging) if ( needsStaging )
{ {
// Since we're going to blit to the texture image, set its layout to eTransferDstOptimal // Since we're going to blit to the texture image, set its layout to eTransferDstOptimal
vk::su::setImageLayout(commandBuffer, image.get(), format, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); vk::su::setImageLayout(
vk::BufferImageCopy copyRegion(0, surfaceData.extent.width, surfaceData.extent.height, vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), vk::Extent3D(surfaceData.extent, 1)); commandBuffer, image.get(), format, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal );
commandBuffer->copyBufferToImage(textureBuffer.get(), image.get(), vk::ImageLayout::eTransferDstOptimal, copyRegion); vk::BufferImageCopy copyRegion( 0,
surfaceData.extent.width,
surfaceData.extent.height,
vk::ImageSubresourceLayers( vk::ImageAspectFlagBits::eColor, 0, 0, 1 ),
vk::Offset3D( 0, 0, 0 ),
vk::Extent3D( surfaceData.extent, 1 ) );
commandBuffer->copyBufferToImage(
textureBuffer.get(), image.get(), vk::ImageLayout::eTransferDstOptimal, copyRegion );
// Set the layout for the texture image from eTransferDstOptimal to SHADER_READ_ONLY // Set the layout for the texture image from eTransferDstOptimal to SHADER_READ_ONLY
vk::su::setImageLayout(commandBuffer, image.get(), format, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); vk::su::setImageLayout( commandBuffer,
image.get(),
format,
vk::ImageLayout::eTransferDstOptimal,
vk::ImageLayout::eShaderReadOnlyOptimal );
} }
else else
{ {
// If we can use the linear tiled image as a texture, just do it // If we can use the linear tiled image as a texture, just do it
vk::su::setImageLayout(commandBuffer, image.get(), format, vk::ImageLayout::ePreinitialized, vk::ImageLayout::eShaderReadOnlyOptimal); vk::su::setImageLayout(
commandBuffer, image.get(), format, vk::ImageLayout::ePreinitialized, vk::ImageLayout::eShaderReadOnlyOptimal );
} }
commandBuffer->end(); commandBuffer->end();
vk::su::submitAndWait(device, graphicsQueue, commandBuffer); vk::su::submitAndWait( device, graphicsQueue, commandBuffer );
vk::UniqueSampler sampler = device->createSamplerUnique(vk::SamplerCreateInfo(vk::SamplerCreateFlags(), vk::Filter::eNearest, vk::Filter::eNearest, vk::SamplerMipmapMode::eNearest, vk::UniqueSampler sampler =
vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, 0.0f, false, 1.0f, false, vk::CompareOp::eNever, 0.0f, 0.0f, device->createSamplerUnique( vk::SamplerCreateInfo( vk::SamplerCreateFlags(),
vk::BorderColor::eFloatOpaqueWhite)); vk::Filter::eNearest,
vk::Filter::eNearest,
vk::SamplerMipmapMode::eNearest,
vk::SamplerAddressMode::eClampToEdge,
vk::SamplerAddressMode::eClampToEdge,
vk::SamplerAddressMode::eClampToEdge,
0.0f,
false,
1.0f,
false,
vk::CompareOp::eNever,
0.0f,
0.0f,
vk::BorderColor::eFloatOpaqueWhite ) );
vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA); vk::ComponentMapping componentMapping(
vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), image.get(), vk::ImageViewType::e2D, format, componentMapping, vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA );
vk::UniqueImageView imageView = device->createImageViewUnique(imageViewCreateInfo); vk::ImageViewCreateInfo imageViewCreateInfo(
vk::ImageViewCreateFlags(),
image.get(),
vk::ImageViewType::e2D,
format,
componentMapping,
vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 ) );
vk::UniqueImageView imageView = device->createImageViewUnique( imageViewCreateInfo );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,13 +19,14 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "InputAttachment"; static char const * AppName = "InputAttachment";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
static std::string vertexShaderText = R"( static std::string vertexShaderText = R"(
#version 450 #version 450
@ -43,7 +44,7 @@ void main()
)"; )";
// Use subpassLoad to read from input attachment // Use subpassLoad to read from input attachment
static const char *fragmentShaderText = R"( static const char * fragmentShaderText = R"(
#version 450 #version 450
layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputAttachment; layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputAttachment;
@ -55,147 +56,239 @@ void main()
outColor = subpassLoad(inputAttachment); outColor = subpassLoad(inputAttachment);
} }
)"; )";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(vk::Format::eR8G8B8A8Unorm); vk::FormatProperties formatProperties = physicalDevice.getFormatProperties( vk::Format::eR8G8B8A8Unorm );
if (!(formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eColorAttachment)) if ( !( formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eColorAttachment ) )
{ {
std::cout << "vk::Format::eR8G8B8A8Unorm format unsupported for input attachment\n"; std::cout << "vk::Format::eR8G8B8A8Unorm format unsupported for input attachment\n";
exit(-1); exit( -1 );
} }
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Create a framebuffer with 2 attachments, one the color attachment the shaders render into, and the other an input attachment which // Create a framebuffer with 2 attachments, one the color attachment the shaders render into, and the other an input
// will be cleared to yellow, and then used by the shaders to color the drawn triangle. Final result should be a yellow triangle // attachment which will be cleared to yellow, and then used by the shaders to color the drawn triangle. Final
// result should be a yellow triangle
// Create the image that will be used as the input attachment // Create the image that will be used as the input attachment
// The image for the color attachment is the presentable image already created as part of the SwapChainData // The image for the color attachment is the presentable image already created as part of the SwapChainData
vk::UniqueImage inputImage = device->createImageUnique(vk::ImageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, swapChainData.colorFormat, vk::Extent3D(surfaceData.extent, 1), 1, 1, vk::UniqueImage inputImage = device->createImageUnique(
vk::SampleCountFlagBits::e1, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eInputAttachment | vk::ImageUsageFlagBits::eTransferDst)); vk::ImageCreateInfo( vk::ImageCreateFlags(),
vk::ImageType::e2D,
swapChainData.colorFormat,
vk::Extent3D( surfaceData.extent, 1 ),
1,
1,
vk::SampleCountFlagBits::e1,
vk::ImageTiling::eOptimal,
vk::ImageUsageFlagBits::eInputAttachment | vk::ImageUsageFlagBits::eTransferDst ) );
vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements(inputImage.get()); vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements( inputImage.get() );
uint32_t memoryTypeIndex = vk::su::findMemoryType(physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlags()); uint32_t memoryTypeIndex = vk::su::findMemoryType(
vk::UniqueDeviceMemory inputMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlags() );
device->bindImageMemory(inputImage.get(), inputMemory.get(), 0); vk::UniqueDeviceMemory inputMemory =
device->allocateMemoryUnique( vk::MemoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ) );
device->bindImageMemory( inputImage.get(), inputMemory.get(), 0 );
// Set the image layout to TRANSFER_DST_OPTIMAL to be ready for clear // Set the image layout to TRANSFER_DST_OPTIMAL to be ready for clear
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
vk::su::setImageLayout(commandBuffer, inputImage.get(), swapChainData.colorFormat, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); vk::su::setImageLayout( commandBuffer,
inputImage.get(),
swapChainData.colorFormat,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eTransferDstOptimal );
commandBuffer->clearColorImage(inputImage.get(), vk::ImageLayout::eTransferDstOptimal, vk::ClearColorValue(std::array<float, 4>({ {1.0f, 1.0f, 0.0f, 0.0f} })), commandBuffer->clearColorImage(
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS)); inputImage.get(),
vk::ImageLayout::eTransferDstOptimal,
vk::ClearColorValue( std::array<float, 4>( { { 1.0f, 1.0f, 0.0f, 0.0f } } ) ),
vk::ImageSubresourceRange(
vk::ImageAspectFlagBits::eColor, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS ) );
// Set the image layout to SHADER_READONLY_OPTIMAL for use by the shaders // Set the image layout to SHADER_READONLY_OPTIMAL for use by the shaders
vk::su::setImageLayout(commandBuffer, inputImage.get(), swapChainData.colorFormat, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); vk::su::setImageLayout( commandBuffer,
inputImage.get(),
swapChainData.colorFormat,
vk::ImageLayout::eTransferDstOptimal,
vk::ImageLayout::eShaderReadOnlyOptimal );
vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA); vk::ComponentMapping componentMapping(
vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), inputImage.get(), vk::ImageViewType::e2D, swapChainData.colorFormat, componentMapping, vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA );
vk::UniqueImageView inputAttachmentView = device->createImageViewUnique(imageViewCreateInfo); vk::ImageViewCreateInfo imageViewCreateInfo(
vk::ImageViewCreateFlags(),
inputImage.get(),
vk::ImageViewType::e2D,
swapChainData.colorFormat,
componentMapping,
vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 ) );
vk::UniqueImageView inputAttachmentView = device->createImageViewUnique( imageViewCreateInfo );
vk::DescriptorSetLayoutBinding layoutBinding(0, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment); vk::DescriptorSetLayoutBinding layoutBinding(
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), 1, &layoutBinding)); 0, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment );
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(
vk::DescriptorSetLayoutCreateInfo( vk::DescriptorSetLayoutCreateFlags(), 1, &layoutBinding ) );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::AttachmentDescription attachments[2] = vk::AttachmentDescription attachments[2] = {
{ // First attachment is the color attachment - clear at the beginning of the renderpass and transition layout to
// First attachment is the color attachment - clear at the beginning of the renderpass and transition layout to PRESENT_SRC_KHR at the end of renderpass // PRESENT_SRC_KHR at the end of renderpass
vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), swapChainData.colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore, vk::AttachmentDescription( vk::AttachmentDescriptionFlags(),
vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR), swapChainData.colorFormat,
vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eClear,
vk::AttachmentStoreOp::eStore,
vk::AttachmentLoadOp::eDontCare,
vk::AttachmentStoreOp::eDontCare,
vk::ImageLayout::eUndefined,
vk::ImageLayout::ePresentSrcKHR ),
// Second attachment is input attachment. Once cleared it should have width*height yellow pixels. // Second attachment is input attachment. Once cleared it should have width*height yellow pixels.
// Doing a subpassLoad in the fragment shader should give the shader the color at the fragments x,y location from the input attachment // Doing a subpassLoad in the fragment shader should give the shader the color at the fragments x,y location from
vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), swapChainData.colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eDontCare, // the input attachment
vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eShaderReadOnlyOptimal) vk::AttachmentDescription( vk::AttachmentDescriptionFlags(),
swapChainData.colorFormat,
vk::SampleCountFlagBits::e1,
vk::AttachmentLoadOp::eLoad,
vk::AttachmentStoreOp::eDontCare,
vk::AttachmentLoadOp::eDontCare,
vk::AttachmentStoreOp::eDontCare,
vk::ImageLayout::eShaderReadOnlyOptimal,
vk::ImageLayout::eShaderReadOnlyOptimal )
}; };
vk::AttachmentReference colorReference(0, vk::ImageLayout::eColorAttachmentOptimal); vk::AttachmentReference colorReference( 0, vk::ImageLayout::eColorAttachmentOptimal );
vk::AttachmentReference inputReference(1, vk::ImageLayout::eShaderReadOnlyOptimal); vk::AttachmentReference inputReference( 1, vk::ImageLayout::eShaderReadOnlyOptimal );
vk::SubpassDescription subPass(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 1, &inputReference, 1, &colorReference); vk::SubpassDescription subPass(
vk::UniqueRenderPass renderPass = device->createRenderPassUnique(vk::RenderPassCreateInfo(vk::RenderPassCreateFlags(), 2, attachments, 1, &subPass)); vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 1, &inputReference, 1, &colorReference );
vk::UniqueRenderPass renderPass = device->createRenderPassUnique(
vk::RenderPassCreateInfo( vk::RenderPassCreateFlags(), 2, attachments, 1, &subPass ) );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, inputAttachmentView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, inputAttachmentView, surfaceData.extent );
vk::DescriptorPoolSize poolSize(vk::DescriptorType::eInputAttachment, 1); vk::DescriptorPoolSize poolSize( vk::DescriptorType::eInputAttachment, 1 );
vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 1, &poolSize)); vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(
vk::DescriptorPoolCreateInfo( vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 1, &poolSize ) );
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::DescriptorImageInfo inputImageInfo(nullptr, inputAttachmentView.get(), vk::ImageLayout::eShaderReadOnlyOptimal); vk::DescriptorImageInfo inputImageInfo(
vk::WriteDescriptorSet writeDescriptorSet(descriptorSet.get(), 0, 0, 1, vk::DescriptorType::eInputAttachment, &inputImageInfo); nullptr, inputAttachmentView.get(), vk::ImageLayout::eShaderReadOnlyOptimal );
device->updateDescriptorSets(vk::ArrayProxy<const vk::WriteDescriptorSet>(1, &writeDescriptorSet), nullptr); vk::WriteDescriptorSet writeDescriptorSet(
descriptorSet.get(), 0, 0, 1, vk::DescriptorType::eInputAttachment, &inputImageInfo );
device->updateDescriptorSets( vk::ArrayProxy<const vk::WriteDescriptorSet>( 1, &writeDescriptorSet ), nullptr );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), 0, {}, vk::UniquePipeline graphicsPipeline =
vk::FrontFace::eClockwise, false, pipelineLayout, renderPass); vk::su::createGraphicsPipeline( device,
pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
0,
{},
vk::FrontFace::eClockwise,
false,
pipelineLayout,
renderPass );
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> result = device->acquireNextImage2KHR(vk::AcquireNextImageInfoKHR(swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get(), {}, 1)); vk::ResultValue<uint32_t> result = device->acquireNextImage2KHR(
assert(result.result == vk::Result::eSuccess); vk::AcquireNextImageInfoKHR( swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get(), {}, 1 ) );
assert( result.result == vk::Result::eSuccess );
uint32_t currentBuffer = result.value; uint32_t currentBuffer = result.value;
vk::ClearValue clearValue; vk::ClearValue clearValue;
clearValue.color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValue.color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
commandBuffer->beginRenderPass(vk::RenderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 1, &clearValue), vk::SubpassContents::eInline); commandBuffer->beginRenderPass( vk::RenderPassBeginInfo( renderPass.get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); framebuffers[currentBuffer].get(),
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr); vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
1,
&clearValue ),
vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(3, 1, 0, 0); commandBuffer->draw( 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
vk::su::submitAndWait(device, graphicsQueue, commandBuffer); vk::su::submitAndWait( device, graphicsQueue, commandBuffer );
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer)); presentQueue.presentKHR( vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer ) );
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -13,16 +13,18 @@
// limitations under the License. // limitations under the License.
// //
// VulkanHpp Samples : InstanceExtensionProperties // VulkanHpp Samples : InstanceExtensionProperties
// Get global extension properties to know what extension are available to enable at CreateInstance time. // Get global extension properties to know what extension are available to enable at CreateInstance
// time.
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
static char const* AppName = "InstanceExtensionProperties"; static char const * AppName = "InstanceExtensionProperties";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
@ -32,10 +34,14 @@ int main(int /*argc*/, char ** /*argv*/)
// sort the extensions alphabetically // sort the extensions alphabetically
std::sort(extensionProperties.begin(), extensionProperties.end(), [](vk::ExtensionProperties const& a, vk::ExtensionProperties const& b) { return strcmp(a.extensionName, b.extensionName) < 0; }); std::sort( extensionProperties.begin(),
extensionProperties.end(),
[]( vk::ExtensionProperties const & a, vk::ExtensionProperties const & b ) {
return strcmp( a.extensionName, b.extensionName ) < 0;
} );
std::cout << "Instance Extensions:" << std::endl; std::cout << "Instance Extensions:" << std::endl;
for (auto const& ep : extensionProperties) for ( auto const & ep : extensionProperties )
{ {
std::cout << ep.extensionName << ":" << std::endl; std::cout << ep.extensionName << ":" << std::endl;
std::cout << "\tVersion: " << ep.specVersion << std::endl; std::cout << "\tVersion: " << ep.specVersion << std::endl;
@ -44,20 +50,20 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -16,25 +16,26 @@
// Get list of global layers and their associated extensions, if any. // Get list of global layers and their associated extensions, if any.
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
static char const* AppName = "InstanceLayerExtensionProperties"; static char const * AppName = "InstanceLayerExtensionProperties";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
struct PropertyData struct PropertyData
{ {
PropertyData(vk::LayerProperties const& layerProperties_, std::vector<vk::ExtensionProperties> const& extensionProperties_) PropertyData( vk::LayerProperties const & layerProperties_,
: layerProperties(layerProperties_) std::vector<vk::ExtensionProperties> const & extensionProperties_ )
, extensionProperties(extensionProperties_) : layerProperties( layerProperties_ ), extensionProperties( extensionProperties_ )
{} {}
vk::LayerProperties layerProperties; vk::LayerProperties layerProperties;
std::vector<vk::ExtensionProperties> extensionProperties; std::vector<vk::ExtensionProperties> extensionProperties;
}; };
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
@ -43,35 +44,36 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
std::vector<PropertyData> propertyData; std::vector<PropertyData> propertyData;
propertyData.reserve(layerProperties.size()); propertyData.reserve( layerProperties.size() );
for (auto const& layerProperty : layerProperties) for ( auto const & layerProperty : layerProperties )
{ {
std::vector<vk::ExtensionProperties> extensionProperties = vk::enumerateInstanceExtensionProperties(std::string(layerProperty.layerName)); std::vector<vk::ExtensionProperties> extensionProperties =
propertyData.push_back(PropertyData(layerProperty, extensionProperties)); vk::enumerateInstanceExtensionProperties( std::string( layerProperty.layerName ) );
propertyData.push_back( PropertyData( layerProperty, extensionProperties ) );
} }
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
std::cout << "Instance Layers:" << std::endl; std::cout << "Instance Layers:" << std::endl;
if (propertyData.empty()) if ( propertyData.empty() )
{ {
std::cout << "Set the environment variable VK_LAYER_PATH to point to the location of your layers" << std::endl; std::cout << "Set the environment variable VK_LAYER_PATH to point to the location of your layers" << std::endl;
} }
else else
{ {
for (auto const& pd : propertyData) for ( auto const & pd : propertyData )
{ {
std::cout << pd.layerProperties.layerName << std::endl; std::cout << pd.layerProperties.layerName << std::endl;
if (pd.extensionProperties.empty()) if ( pd.extensionProperties.empty() )
{ {
std::cout << "Layer Extension: None"; std::cout << "Layer Extension: None";
} }
else else
{ {
for (auto it = pd.extensionProperties.begin(); it != pd.extensionProperties.end(); ++it) for ( auto it = pd.extensionProperties.begin(); it != pd.extensionProperties.end(); ++it )
{ {
if (it != pd.extensionProperties.begin()) if ( it != pd.extensionProperties.begin() )
{ {
std::cout << ", "; std::cout << ", ";
} }
@ -83,20 +85,20 @@ int main(int /*argc*/, char ** /*argv*/)
} }
std::cout << std::endl; std::cout << std::endl;
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -15,16 +15,16 @@
// VulkanHpp Samples : InstanceLayerProperties // VulkanHpp Samples : InstanceLayerProperties
// Get global layer properties to know what layers are available to enable at CreateInstance time. // Get global layer properties to know what layers are available to enable at CreateInstance time.
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
static char const* AppName = "InstanceLayerProperties"; static char const * AppName = "InstanceLayerProperties";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
@ -33,35 +33,36 @@ int main(int /*argc*/, char ** /*argv*/)
std::vector<vk::LayerProperties> layerProperties = vk::enumerateInstanceLayerProperties(); std::vector<vk::LayerProperties> layerProperties = vk::enumerateInstanceLayerProperties();
std::cout << "Instance Layers:" << std::endl; std::cout << "Instance Layers:" << std::endl;
if (layerProperties.empty()) if ( layerProperties.empty() )
{ {
std::cout << "Set the environment variable VK_LAYER_PATH to point to the location of your layers" << std::endl; std::cout << "Set the environment variable VK_LAYER_PATH to point to the location of your layers" << std::endl;
} }
for (auto const& lp : layerProperties) for ( auto const & lp : layerProperties )
{ {
std::cout << lp.layerName << ":" << std::endl; std::cout << lp.layerName << ":" << std::endl;
std::cout << "\tVersion: " << lp.implementationVersion << std::endl; std::cout << "\tVersion: " << lp.implementationVersion << std::endl;
std::cout << "\tAPI Version: (" << (lp.specVersion >> 22) << "." << ((lp.specVersion >> 12) & 0x03FF) << "." << (lp.specVersion & 0xFFF) << ")" << std::endl; std::cout << "\tAPI Version: (" << ( lp.specVersion >> 22 ) << "." << ( ( lp.specVersion >> 12 ) & 0x03FF ) << "."
<< ( lp.specVersion & 0xFFF ) << ")" << std::endl;
std::cout << "\tDescription: " << lp.description << std::endl; std::cout << "\tDescription: " << lp.description << std::endl;
std::cout << std::endl; std::cout << std::endl;
} }
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -16,42 +16,44 @@
// Get the version of instance-level functionality supported by the implementation. // Get the version of instance-level functionality supported by the implementation.
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
static char const* AppName = "InstanceVersion"; static char const * AppName = "InstanceVersion";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
std::string decodeAPIVersion(uint32_t apiVersion) std::string decodeAPIVersion( uint32_t apiVersion )
{ {
return std::to_string(VK_VERSION_MAJOR(apiVersion)) + "." + std::to_string(VK_VERSION_MINOR(apiVersion)) + "." + std::to_string(VK_VERSION_PATCH(apiVersion)); return std::to_string( VK_VERSION_MAJOR( apiVersion ) ) + "." + std::to_string( VK_VERSION_MINOR( apiVersion ) ) +
"." + std::to_string( VK_VERSION_PATCH( apiVersion ) );
} }
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
uint32_t apiVersion = vk::enumerateInstanceVersion(); uint32_t apiVersion = vk::enumerateInstanceVersion();
std::cout << "APIVersion = " << decodeAPIVersion(apiVersion); std::cout << "APIVersion = " << decodeAPIVersion( apiVersion );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,13 +19,14 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "MultipleSets"; static char const * AppName = "MultipleSets";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
const std::string vertexShaderText = R"( const std::string vertexShaderText = R"(
#version 400 #version 400
@ -77,145 +78,200 @@ void main()
} }
)"; )";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::TextureData textureData(physicalDevice, device); vk::su::TextureData textureData( physicalDevice, device );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
textureData.setImage(device, commandBuffer, vk::su::MonochromeImageGenerator({ 118, 185, 0 })); textureData.setImage( device, commandBuffer, vk::su::MonochromeImageGenerator( { 118, 185, 0 } ) );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Create first layout to contain uniform buffer data // Create first layout to contain uniform buffer data
vk::DescriptorSetLayoutBinding uniformBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex); vk::DescriptorSetLayoutBinding uniformBinding(
vk::UniqueDescriptorSetLayout uniformLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), 1, &uniformBinding)); 0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex );
vk::UniqueDescriptorSetLayout uniformLayout = device->createDescriptorSetLayoutUnique(
vk::DescriptorSetLayoutCreateInfo( vk::DescriptorSetLayoutCreateFlags(), 1, &uniformBinding ) );
// Create second layout containing combined sampler/image data // Create second layout containing combined sampler/image data
vk::DescriptorSetLayoutBinding sampler2DBinding(0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eVertex); vk::DescriptorSetLayoutBinding sampler2DBinding(
vk::UniqueDescriptorSetLayout samplerLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), 1, &sampler2DBinding)); 0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eVertex );
vk::UniqueDescriptorSetLayout samplerLayout = device->createDescriptorSetLayoutUnique(
vk::DescriptorSetLayoutCreateInfo( vk::DescriptorSetLayoutCreateFlags(), 1, &sampler2DBinding ) );
// Create pipeline layout with multiple descriptor sets // Create pipeline layout with multiple descriptor sets
std::array<vk::DescriptorSetLayout, 2> descriptorSetLayouts = { uniformLayout.get(), samplerLayout.get() }; std::array<vk::DescriptorSetLayout, 2> descriptorSetLayouts = { uniformLayout.get(), samplerLayout.get() };
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 2, descriptorSetLayouts.data())); vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 2, descriptorSetLayouts.data() ) );
// Create a single pool to contain data for our two descriptor sets // Create a single pool to contain data for our two descriptor sets
vk::DescriptorPoolSize poolSizes[2] = vk::DescriptorPoolSize poolSizes[2] = { vk::DescriptorPoolSize( vk::DescriptorType::eUniformBuffer, 1 ),
{ vk::DescriptorPoolSize( vk::DescriptorType::eCombinedImageSampler, 1 ) };
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1), vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(
vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, 1) vk::DescriptorPoolCreateInfo( vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 2, 2, poolSizes ) );
};
vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 2, 2, poolSizes));
// Populate descriptor sets // Populate descriptor sets
std::vector<vk::UniqueDescriptorSet> descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 2, descriptorSetLayouts.data())); std::vector<vk::UniqueDescriptorSet> descriptorSets = device->allocateDescriptorSetsUnique(
vk::DescriptorSetAllocateInfo( descriptorPool.get(), 2, descriptorSetLayouts.data() ) );
// Populate with info about our uniform buffer // Populate with info about our uniform buffer
vk::DescriptorBufferInfo uniformBufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); vk::DescriptorBufferInfo uniformBufferInfo( uniformBufferData.buffer.get(), 0, sizeof( glm::mat4x4 ) );
vk::DescriptorImageInfo textureImageInfo(textureData.textureSampler.get(), textureData.imageData->imageView.get(), vk::ImageLayout::eShaderReadOnlyOptimal); vk::DescriptorImageInfo textureImageInfo( textureData.textureSampler.get(),
std::array<vk::WriteDescriptorSet, 2> writeDescriptorSets = textureData.imageData->imageView.get(),
{ vk::ImageLayout::eShaderReadOnlyOptimal );
vk::WriteDescriptorSet(descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniformBufferInfo), std::array<vk::WriteDescriptorSet, 2> writeDescriptorSets = {
vk::WriteDescriptorSet(descriptorSets[1].get(), 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &textureImageInfo) vk::WriteDescriptorSet(
descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniformBufferInfo ),
vk::WriteDescriptorSet(
descriptorSets[1].get(), 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &textureImageInfo )
}; };
device->updateDescriptorSets(writeDescriptorSets, nullptr); device->updateDescriptorSets( writeDescriptorSets, nullptr );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline =
sizeof(texturedCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } }, vk::su::createGraphicsPipeline( device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( texturedCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); framebuffers[currentBuffer.value].get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, { descriptorSets[0].get(), descriptorSets[1].get() }, nullptr); 2,
clearValues );
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets( vk::PipelineBindPoint::eGraphics,
pipelineLayout.get(),
0,
{ descriptorSets[0].get(), descriptorSets[1].get() },
nullptr );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,161 +19,238 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "OcclusionQuery"; static char const * AppName = "OcclusionQuery";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, { {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex} }); vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); device, { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PC_C );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(coloredCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, coloredCubeData, sizeof(coloredCubeData) / sizeof(coloredCubeData[0])); physicalDevice, device, sizeof( coloredCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
coloredCubeData,
sizeof( coloredCubeData ) / sizeof( coloredCubeData[0] ) );
vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, { {vk::DescriptorType::eUniformBuffer, 1} }); vk::UniqueDescriptorPool descriptorPool =
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); vk::su::createDescriptorPool( device, { { vk::DescriptorType::eUniformBuffer, 1 } } );
vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::su::updateDescriptorSets(device, descriptorSet, {{vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView()}}, {}); vk::su::updateDescriptorSets(
device,
descriptorSet,
{ { vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView() } },
{} );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(
sizeof(coloredCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32B32A32Sfloat, 16 } }, device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( coloredCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32B32A32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo(vk::SemaphoreCreateFlags())); vk::UniqueSemaphore imageAcquiredSemaphore =
device->createSemaphoreUnique( vk::SemaphoreCreateInfo( vk::SemaphoreCreateFlags() ) );
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer =
assert(currentBuffer.result == vk::Result::eSuccess); device->acquireNextImageKHR( swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
/* Allocate a uniform buffer that will take query results. */ /* Allocate a uniform buffer that will take query results. */
vk::UniqueBuffer queryResultBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), 4 * sizeof(uint64_t), vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eTransferDst)); vk::UniqueBuffer queryResultBuffer = device->createBufferUnique(
vk::BufferCreateInfo( vk::BufferCreateFlags(),
4 * sizeof( uint64_t ),
vk::BufferUsageFlagBits::eUniformBuffer | vk::BufferUsageFlagBits::eTransferDst ) );
vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements(queryResultBuffer.get()); vk::MemoryRequirements memoryRequirements = device->getBufferMemoryRequirements( queryResultBuffer.get() );
uint32_t memoryTypeIndex = vk::su::findMemoryType(physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); uint32_t memoryTypeIndex =
vk::UniqueDeviceMemory queryResultMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex)); vk::su::findMemoryType( physicalDevice.getMemoryProperties(),
memoryRequirements.memoryTypeBits,
vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent );
vk::UniqueDeviceMemory queryResultMemory =
device->allocateMemoryUnique( vk::MemoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ) );
device->bindBufferMemory(queryResultBuffer.get(), queryResultMemory.get(), 0); device->bindBufferMemory( queryResultBuffer.get(), queryResultMemory.get(), 0 );
vk::UniqueQueryPool queryPool = device->createQueryPoolUnique(vk::QueryPoolCreateInfo(vk::QueryPoolCreateFlags(), vk::QueryType::eOcclusion, 2, vk::QueryPipelineStatisticFlags())); vk::UniqueQueryPool queryPool = device->createQueryPoolUnique( vk::QueryPoolCreateInfo(
vk::QueryPoolCreateFlags(), vk::QueryType::eOcclusion, 2, vk::QueryPipelineStatisticFlags() ) );
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlags())); commandBuffer->begin( vk::CommandBufferBeginInfo( vk::CommandBufferUsageFlags() ) );
commandBuffer->resetQueryPool(queryPool.get(), 0, 2); commandBuffer->resetQueryPool( queryPool.get(), 0, 2 );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
commandBuffer->beginRenderPass(vk::RenderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(), surfaceData.extent), 2, clearValues), vk::SubpassContents::eInline); commandBuffer->beginRenderPass( vk::RenderPassBeginInfo( renderPass.get(),
framebuffers[currentBuffer.value].get(),
vk::Rect2D( vk::Offset2D(), surfaceData.extent ),
2,
clearValues ),
vk::SubpassContents::eInline );
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), {}); commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), {} );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->beginQuery(queryPool.get(), 0, vk::QueryControlFlags()); commandBuffer->beginQuery( queryPool.get(), 0, vk::QueryControlFlags() );
commandBuffer->endQuery(queryPool.get(), 0); commandBuffer->endQuery( queryPool.get(), 0 );
commandBuffer->beginQuery(queryPool.get(), 1, vk::QueryControlFlags()); commandBuffer->beginQuery( queryPool.get(), 1, vk::QueryControlFlags() );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->endQuery(queryPool.get(), 1); commandBuffer->endQuery( queryPool.get(), 1 );
commandBuffer->copyQueryPoolResults(queryPool.get(), 0, 2, queryResultBuffer.get(), 0, sizeof(uint64_t), vk::QueryResultFlagBits::e64 | vk::QueryResultFlagBits::eWait); commandBuffer->copyQueryPoolResults( queryPool.get(),
0,
2,
queryResultBuffer.get(),
0,
sizeof( uint64_t ),
vk::QueryResultFlagBits::e64 | vk::QueryResultFlagBits::eWait );
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
graphicsQueue.waitIdle(); graphicsQueue.waitIdle();
uint64_t samplesPassed[2]; uint64_t samplesPassed[2];
device->getQueryPoolResults(queryPool.get(), 0, 2, vk::ArrayProxy<uint64_t>(4, samplesPassed), sizeof(uint64_t), vk::QueryResultFlagBits::e64 | vk::QueryResultFlagBits::eWait); device->getQueryPoolResults( queryPool.get(),
0,
2,
vk::ArrayProxy<uint64_t>( 4, samplesPassed ),
sizeof( uint64_t ),
vk::QueryResultFlagBits::e64 | vk::QueryResultFlagBits::eWait );
std::cout << "vkGetQueryPoolResults data\n"; std::cout << "vkGetQueryPoolResults data\n";
std::cout << "samples_passed[0] = " << samplesPassed[0] << "\n"; std::cout << "samples_passed[0] = " << samplesPassed[0] << "\n";
std::cout << "samples_passed[1] = " << samplesPassed[1] << "\n"; std::cout << "samples_passed[1] = " << samplesPassed[1] << "\n";
/* Read back query result from buffer */ /* Read back query result from buffer */
uint64_t *samplesPassedPtr = static_cast<uint64_t*>(device->mapMemory(queryResultMemory.get(), 0, memoryRequirements.size, vk::MemoryMapFlags())); uint64_t * samplesPassedPtr = static_cast<uint64_t *>(
device->mapMemory( queryResultMemory.get(), 0, memoryRequirements.size, vk::MemoryMapFlags() ) );
std::cout << "vkCmdCopyQueryPoolResults data\n"; std::cout << "vkCmdCopyQueryPoolResults data\n";
std::cout << "samples_passed[0] = " << samplesPassedPtr[0] << "\n"; std::cout << "samples_passed[0] = " << samplesPassedPtr[0] << "\n";
std::cout << "samples_passed[1] = " << samplesPassedPtr[1] << "\n"; std::cout << "samples_passed[1] = " << samplesPassedPtr[1] << "\n";
device->unmapMemory(queryResultMemory.get()); device->unmapMemory( queryResultMemory.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,18 +17,19 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <vector> #include <vector>
static char const* AppName = "DeviceExtensionProperties"; static char const * AppName = "DeviceExtensionProperties";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
// enumerate the physicalDevices // enumerate the physicalDevices
@ -36,14 +37,19 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
for (size_t i=0 ; i<physicalDevices.size() ; i++) for ( size_t i = 0; i < physicalDevices.size(); i++ )
{ {
std::cout << "PhysicalDevice " << i << "\n"; std::cout << "PhysicalDevice " << i << "\n";
std::vector<vk::ExtensionProperties> extensionProperties = physicalDevices[i].enumerateDeviceExtensionProperties(); std::vector<vk::ExtensionProperties> extensionProperties =
physicalDevices[i].enumerateDeviceExtensionProperties();
// sort the extensions alphabetically // sort the extensions alphabetically
std::sort(extensionProperties.begin(), extensionProperties.end(), [](vk::ExtensionProperties const& a, vk::ExtensionProperties const& b) { return strcmp(a.extensionName, b.extensionName) < 0; }); std::sort( extensionProperties.begin(),
for (auto const& ep : extensionProperties) extensionProperties.end(),
[]( vk::ExtensionProperties const & a, vk::ExtensionProperties const & b ) {
return strcmp( a.extensionName, b.extensionName ) < 0;
} );
for ( auto const & ep : extensionProperties )
{ {
std::cout << "\t" << ep.extensionName << ":" << std::endl; std::cout << "\t" << ep.extensionName << ":" << std::endl;
std::cout << "\t\tVersion: " << ep.specVersion << std::endl; std::cout << "\t\tVersion: " << ep.specVersion << std::endl;
@ -53,20 +59,20 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -17,18 +17,19 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <vector> #include <vector>
static char const* AppName = "PhysicalDeviceGroups"; static char const * AppName = "PhysicalDeviceGroups";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
@ -36,19 +37,22 @@ int main(int /*argc*/, char ** /*argv*/)
std::vector<vk::PhysicalDeviceGroupProperties> groupProperties = instance->enumeratePhysicalDeviceGroups(); std::vector<vk::PhysicalDeviceGroupProperties> groupProperties = instance->enumeratePhysicalDeviceGroups();
std::cout << std::boolalpha; std::cout << std::boolalpha;
for (size_t i=0 ; i< groupProperties.size() ; i++) for ( size_t i = 0; i < groupProperties.size(); i++ )
{ {
std::cout << "Group Properties " << i << "\n"; std::cout << "Group Properties " << i << "\n";
std::cout << "\t" << "physicalDeviceCount = " << groupProperties[i].physicalDeviceCount << "\n"; std::cout << "\t"
std::cout << "\t" << "physicalDevices:\n"; << "physicalDeviceCount = " << groupProperties[i].physicalDeviceCount << "\n";
for (size_t j = 0; j < groupProperties[i].physicalDeviceCount; j++) std::cout << "\t"
<< "physicalDevices:\n";
for ( size_t j = 0; j < groupProperties[i].physicalDeviceCount; j++ )
{ {
std::cout << "\t\t" << j << " : " << groupProperties[i].physicalDevices[j].getProperties().deviceName << "\n"; std::cout << "\t\t" << j << " : " << groupProperties[i].physicalDevices[j].getProperties().deviceName << "\n";
} }
std::cout << "\t" << "subsetAllocation = " << static_cast<bool>(groupProperties[i].subsetAllocation) << "\n"; std::cout << "\t"
<< "subsetAllocation = " << static_cast<bool>( groupProperties[i].subsetAllocation ) << "\n";
std::cout << "\n"; std::cout << "\n";
if (1 < groupProperties[i].physicalDeviceCount) if ( 1 < groupProperties[i].physicalDeviceCount )
{ {
vk::PhysicalDevice physicalDevice = groupProperties[i].physicalDevices[0]; vk::PhysicalDevice physicalDevice = groupProperties[i].physicalDevices[0];
@ -56,40 +60,44 @@ int main(int /*argc*/, char ** /*argv*/)
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties(); std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
// get the first index into queueFamiliyProperties which supports graphics // get the first index into queueFamiliyProperties which supports graphics
size_t graphicsQueueFamilyIndex = std::distance(queueFamilyProperties.begin(), size_t graphicsQueueFamilyIndex = std::distance(
std::find_if(queueFamilyProperties.begin(), queueFamilyProperties.begin(),
queueFamilyProperties.end(), std::find_if(
[](vk::QueueFamilyProperties const& qfp) { return qfp.queueFlags & vk::QueueFlagBits::eGraphics; })); queueFamilyProperties.begin(), queueFamilyProperties.end(), []( vk::QueueFamilyProperties const & qfp ) {
assert(graphicsQueueFamilyIndex < queueFamilyProperties.size()); return qfp.queueFlags & vk::QueueFlagBits::eGraphics;
} ) );
assert( graphicsQueueFamilyIndex < queueFamilyProperties.size() );
// create a UniqueDevice // create a UniqueDevice
float queuePriority = 0.0f; float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), static_cast<uint32_t>(graphicsQueueFamilyIndex), 1, &queuePriority); vk::DeviceQueueCreateInfo deviceQueueCreateInfo(
vk::DeviceCreateInfo deviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo); vk::DeviceQueueCreateFlags(), static_cast<uint32_t>( graphicsQueueFamilyIndex ), 1, &queuePriority );
vk::DeviceCreateInfo deviceCreateInfo( vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo );
vk::DeviceGroupDeviceCreateInfo deviceGroupDeviceCreateInfo(groupProperties[i].physicalDeviceCount, groupProperties[i].physicalDevices); vk::DeviceGroupDeviceCreateInfo deviceGroupDeviceCreateInfo( groupProperties[i].physicalDeviceCount,
groupProperties[i].physicalDevices );
deviceCreateInfo.pNext = &deviceGroupDeviceCreateInfo; deviceCreateInfo.pNext = &deviceGroupDeviceCreateInfo;
vk::UniqueDevice device = physicalDevice.createDeviceUnique(deviceCreateInfo); vk::UniqueDevice device = physicalDevice.createDeviceUnique( deviceCreateInfo );
} }
} }
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,41 +17,42 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <sstream> #include <sstream>
#include <vector> #include <vector>
static char const* AppName = "PhysicalDeviceMemoryProperties"; static char const * AppName = "PhysicalDeviceMemoryProperties";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
std::string formatSize(vk::DeviceSize size) std::string formatSize( vk::DeviceSize size )
{ {
std::ostringstream oss; std::ostringstream oss;
if (size < 1024) if ( size < 1024 )
{ {
oss << size << " B"; oss << size << " B";
} }
else if (size < 1024 * 1024) else if ( size < 1024 * 1024 )
{ {
oss << size / 1024.f << " KB"; oss << size / 1024.f << " KB";
} }
else if (size < 1024 * 1024 * 1024) else if ( size < 1024 * 1024 * 1024 )
{ {
oss << size / (1024.0f * 1024.0f) << " MB"; oss << size / ( 1024.0f * 1024.0f ) << " MB";
} }
else else
{ {
oss << size / (1024.0f * 1024.0f * 1024.0f) << " GB"; oss << size / ( 1024.0f * 1024.0f * 1024.0f ) << " GB";
} }
return oss.str(); return oss.str();
} }
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
// enumerate the physicalDevices // enumerate the physicalDevices
@ -59,48 +60,56 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
for (size_t i=0 ; i<physicalDevices.size() ; i++) for ( size_t i = 0; i < physicalDevices.size(); i++ )
{ {
// some properties are only valid, if a corresponding extension is available! // some properties are only valid, if a corresponding extension is available!
std::vector<vk::ExtensionProperties> extensionProperties = physicalDevices[i].enumerateDeviceExtensionProperties(); std::vector<vk::ExtensionProperties> extensionProperties =
bool containsMemoryBudget = vk::su::contains(extensionProperties, "VK_EXT_memory_budget"); physicalDevices[i].enumerateDeviceExtensionProperties();
bool containsMemoryBudget = vk::su::contains( extensionProperties, "VK_EXT_memory_budget" );
std::cout << "PhysicalDevice " << i << "\n"; std::cout << "PhysicalDevice " << i << "\n";
auto memoryProperties2 = physicalDevices[i].getMemoryProperties2<vk::PhysicalDeviceMemoryProperties2, vk::PhysicalDeviceMemoryBudgetPropertiesEXT>(); auto memoryProperties2 =
vk::PhysicalDeviceMemoryProperties const& memoryProperties = memoryProperties2.get<vk::PhysicalDeviceMemoryProperties2>().memoryProperties; physicalDevices[i]
vk::PhysicalDeviceMemoryBudgetPropertiesEXT const& memoryBudgetProperties = memoryProperties2.get<vk::PhysicalDeviceMemoryBudgetPropertiesEXT>(); .getMemoryProperties2<vk::PhysicalDeviceMemoryProperties2, vk::PhysicalDeviceMemoryBudgetPropertiesEXT>();
vk::PhysicalDeviceMemoryProperties const & memoryProperties =
memoryProperties2.get<vk::PhysicalDeviceMemoryProperties2>().memoryProperties;
vk::PhysicalDeviceMemoryBudgetPropertiesEXT const & memoryBudgetProperties =
memoryProperties2.get<vk::PhysicalDeviceMemoryBudgetPropertiesEXT>();
std::cout << "memoryHeapCount: " << memoryProperties.memoryHeapCount << "\n"; std::cout << "memoryHeapCount: " << memoryProperties.memoryHeapCount << "\n";
for (uint32_t j = 0; j < memoryProperties.memoryHeapCount; j++) for ( uint32_t j = 0; j < memoryProperties.memoryHeapCount; j++ )
{ {
std::cout << " " << j << ": size = " << formatSize(memoryProperties.memoryHeaps[j].size) << ", flags = " << vk::to_string(memoryProperties.memoryHeaps[j].flags) << "\n"; std::cout << " " << j << ": size = " << formatSize( memoryProperties.memoryHeaps[j].size )
if (containsMemoryBudget) << ", flags = " << vk::to_string( memoryProperties.memoryHeaps[j].flags ) << "\n";
if ( containsMemoryBudget )
{ {
std::cout << " heapBudget = " << formatSize(memoryBudgetProperties.heapBudget[j]) << ", heapUsage = " << formatSize(memoryBudgetProperties.heapUsage[j]) << "\n"; std::cout << " heapBudget = " << formatSize( memoryBudgetProperties.heapBudget[j] )
<< ", heapUsage = " << formatSize( memoryBudgetProperties.heapUsage[j] ) << "\n";
} }
} }
std::cout << "memoryTypeCount: " << memoryProperties.memoryTypeCount << "\n"; std::cout << "memoryTypeCount: " << memoryProperties.memoryTypeCount << "\n";
for (uint32_t j = 0; j < memoryProperties.memoryTypeCount; j++) for ( uint32_t j = 0; j < memoryProperties.memoryTypeCount; j++ )
{ {
std::cout << " " << j << ": heapIndex = " << memoryProperties.memoryTypes[j].heapIndex << ", flags = " << vk::to_string(memoryProperties.memoryTypes[j].propertyFlags) << "\n"; std::cout << " " << j << ": heapIndex = " << memoryProperties.memoryTypes[j].heapIndex
<< ", flags = " << vk::to_string( memoryProperties.memoryTypes[j].propertyFlags ) << "\n";
} }
} }
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -17,20 +17,21 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
static char const* AppName = "PhysicalDeviceQueueFamilyProperties"; static char const * AppName = "PhysicalDeviceQueueFamilyProperties";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
// enumerate the physicalDevices // enumerate the physicalDevices
@ -39,32 +40,47 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
std::cout << std::boolalpha; std::cout << std::boolalpha;
for (size_t i=0 ; i<physicalDevices.size() ; i++) for ( size_t i = 0; i < physicalDevices.size(); i++ )
{ {
// some features are only valid, if a corresponding extension is available! // some features are only valid, if a corresponding extension is available!
std::vector<vk::ExtensionProperties> extensionProperties = physicalDevices[i].enumerateDeviceExtensionProperties(); std::vector<vk::ExtensionProperties> extensionProperties =
physicalDevices[i].enumerateDeviceExtensionProperties();
std::cout << "PhysicalDevice " << i << "\n"; std::cout << "PhysicalDevice " << i << "\n";
// need to explicitly specify all the template arguments for getQueueFamilyProperties2 to make the compiler happy // need to explicitly specify all the template arguments for getQueueFamilyProperties2 to make the compiler happy
using Chain = vk::StructureChain<vk::QueueFamilyProperties2, vk::QueueFamilyCheckpointPropertiesNV>; using Chain = vk::StructureChain<vk::QueueFamilyProperties2, vk::QueueFamilyCheckpointPropertiesNV>;
auto queueFamilyProperties2 = physicalDevices[i].getQueueFamilyProperties2<Chain, std::allocator<Chain>, vk::DispatchLoaderDynamic>(); auto queueFamilyProperties2 =
for (size_t j = 0; j < queueFamilyProperties2.size(); j++) physicalDevices[i].getQueueFamilyProperties2<Chain, std::allocator<Chain>, vk::DispatchLoaderDynamic>();
for ( size_t j = 0; j < queueFamilyProperties2.size(); j++ )
{ {
std::cout << "\t" << "QueueFamily " << j << "\n"; std::cout << "\t"
vk::QueueFamilyProperties const& properties = queueFamilyProperties2[j].get<vk::QueueFamilyProperties2>().queueFamilyProperties; << "QueueFamily " << j << "\n";
std::cout << "\t\t" << "QueueFamilyProperties:\n"; vk::QueueFamilyProperties const & properties =
std::cout << "\t\t\t" << "queueFlags = " << vk::to_string(properties.queueFlags) << "\n"; queueFamilyProperties2[j].get<vk::QueueFamilyProperties2>().queueFamilyProperties;
std::cout << "\t\t\t" << "queueCount = " << properties.queueCount << "\n"; std::cout << "\t\t"
std::cout << "\t\t\t" << "timestampValidBits = " << properties.timestampValidBits << "\n"; << "QueueFamilyProperties:\n";
std::cout << "\t\t\t" << "minImageTransferGranularity = " << properties.minImageTransferGranularity.width << " x " << properties.minImageTransferGranularity.height << " x " << properties.minImageTransferGranularity.depth << "\n"; std::cout << "\t\t\t"
<< "queueFlags = " << vk::to_string( properties.queueFlags ) << "\n";
std::cout << "\t\t\t"
<< "queueCount = " << properties.queueCount << "\n";
std::cout << "\t\t\t"
<< "timestampValidBits = " << properties.timestampValidBits << "\n";
std::cout << "\t\t\t"
<< "minImageTransferGranularity = " << properties.minImageTransferGranularity.width << " x "
<< properties.minImageTransferGranularity.height << " x "
<< properties.minImageTransferGranularity.depth << "\n";
std::cout << "\n"; std::cout << "\n";
if (vk::su::contains(extensionProperties, "VK_NV_device_diagnostic_checkpoints")) if ( vk::su::contains( extensionProperties, "VK_NV_device_diagnostic_checkpoints" ) )
{ {
vk::QueueFamilyCheckpointPropertiesNV const& checkpointProperties = queueFamilyProperties2[j].get<vk::QueueFamilyCheckpointPropertiesNV>(); vk::QueueFamilyCheckpointPropertiesNV const & checkpointProperties =
std::cout << "\t\t" << "CheckPointPropertiesNV:\n"; queueFamilyProperties2[j].get<vk::QueueFamilyCheckpointPropertiesNV>();
std::cout << "\t\t\t" << "checkpointExecutionStageMask = " << vk::to_string(checkpointProperties.checkpointExecutionStageMask) << "\n"; std::cout << "\t\t"
<< "CheckPointPropertiesNV:\n";
std::cout << "\t\t\t"
<< "checkpointExecutionStageMask = "
<< vk::to_string( checkpointProperties.checkpointExecutionStageMask ) << "\n";
std::cout << "\n"; std::cout << "\n";
} }
} }
@ -72,20 +88,20 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,30 +19,31 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <fstream> #include <fstream>
#include <iomanip> #include <iomanip>
#include <thread> #include <thread>
// For timestamp code (getMilliseconds) // For timestamp code (getMilliseconds)
#ifdef WIN32 #ifdef WIN32
#include <Windows.h> # include <Windows.h>
#else #else
#include <sys/time.h> # include <sys/time.h>
#endif #endif
typedef unsigned long long timestamp_t; typedef unsigned long long timestamp_t;
timestamp_t getMilliseconds() timestamp_t getMilliseconds()
{ {
#ifdef WIN32 #ifdef WIN32
LARGE_INTEGER frequency; LARGE_INTEGER frequency;
BOOL useQPC = QueryPerformanceFrequency(&frequency); BOOL useQPC = QueryPerformanceFrequency( &frequency );
if (useQPC) if ( useQPC )
{ {
LARGE_INTEGER now; LARGE_INTEGER now;
QueryPerformanceCounter(&now); QueryPerformanceCounter( &now );
return (1000LL * now.QuadPart) / frequency.QuadPart; return ( 1000LL * now.QuadPart ) / frequency.QuadPart;
} }
else else
{ {
@ -50,91 +51,124 @@ timestamp_t getMilliseconds()
} }
#else #else
struct timeval now; struct timeval now;
gettimeofday(&now, NULL); gettimeofday( &now, NULL );
return (now.tv_usec / 1000) + (timestamp_t)now.tv_sec; return ( now.tv_usec / 1000 ) + (timestamp_t)now.tv_sec;
#endif #endif
} }
static char const * AppName = "PipelineCache";
static char const * EngineName = "Vulkan.hpp";
static char const* AppName = "PipelineCache"; int main( int /*argc*/, char ** /*argv*/ )
static char const* EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/)
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::PhysicalDeviceProperties properties = physicalDevice.getProperties(); vk::PhysicalDeviceProperties properties = physicalDevice.getProperties();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::TextureData textureData(physicalDevice, device); vk::su::TextureData textureData( physicalDevice, device );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
textureData.setImage(device, commandBuffer, vk::su::MonochromeImageGenerator({ 118, 185, 0 })); textureData.setImage( device, commandBuffer, vk::su::MonochromeImageGenerator( { 118, 185, 0 } ) );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
{ {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex}, {vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment} }); device,
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex },
{ vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, { {vk::DescriptorType::eUniformBuffer, 1}, {vk::DescriptorType::eCombinedImageSampler, 1} }); vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); device, { { vk::DescriptorType::eUniformBuffer, 1 }, { vk::DescriptorType::eCombinedImageSampler, 1 } } );
vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::su::updateDescriptorSets(device, descriptorSet, {{vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView()}}, textureData); vk::su::updateDescriptorSets(
device,
descriptorSet,
{ { vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView() } },
textureData );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Check disk for existing cache data // Check disk for existing cache data
size_t startCacheSize = 0; size_t startCacheSize = 0;
char *startCacheData = nullptr; char * startCacheData = nullptr;
std::string cacheFileName = "pipeline_cache_data.bin"; std::string cacheFileName = "pipeline_cache_data.bin";
std::ifstream readCacheStream(cacheFileName, std::ios_base::in | std::ios_base::binary); std::ifstream readCacheStream( cacheFileName, std::ios_base::in | std::ios_base::binary );
if (readCacheStream.good()) if ( readCacheStream.good() )
{ {
// Determine cache size // Determine cache size
readCacheStream.seekg(0, readCacheStream.end); readCacheStream.seekg( 0, readCacheStream.end );
startCacheSize = vk::su::checked_cast<size_t>(readCacheStream.tellg()); startCacheSize = vk::su::checked_cast<size_t>( readCacheStream.tellg() );
readCacheStream.seekg(0, readCacheStream.beg); readCacheStream.seekg( 0, readCacheStream.beg );
// Allocate memory to hold the initial cache data // Allocate memory to hold the initial cache data
startCacheData = (char *)std::malloc(startCacheSize); startCacheData = (char *)std::malloc( startCacheSize );
// Read the data into our buffer // Read the data into our buffer
readCacheStream.read(startCacheData, startCacheSize); readCacheStream.read( startCacheData, startCacheSize );
// Clean up and print results // Clean up and print results
readCacheStream.close(); readCacheStream.close();
@ -147,7 +181,7 @@ int main(int /*argc*/, char ** /*argv*/)
std::cout << " Pipeline cache miss!\n"; std::cout << " Pipeline cache miss!\n";
} }
if (startCacheData != nullptr) if ( startCacheData != nullptr )
{ {
// Check for cache validity // Check for cache validity
// //
@ -177,136 +211,160 @@ int main(int /*argc*/, char ** /*argv*/)
// as a stream of bytes, with the least significant byte first // as a stream of bytes, with the least significant byte first
// 16 VK_UUID_SIZE a pipeline cache ID equal to VkPhysicalDeviceProperties::pipelineCacheUUID // 16 VK_UUID_SIZE a pipeline cache ID equal to VkPhysicalDeviceProperties::pipelineCacheUUID
uint32_t headerLength = 0; uint32_t headerLength = 0;
uint32_t cacheHeaderVersion = 0; uint32_t cacheHeaderVersion = 0;
uint32_t vendorID = 0; uint32_t vendorID = 0;
uint32_t deviceID = 0; uint32_t deviceID = 0;
uint8_t pipelineCacheUUID[VK_UUID_SIZE] = {}; uint8_t pipelineCacheUUID[VK_UUID_SIZE] = {};
memcpy(&headerLength, (uint8_t *)startCacheData + 0, 4); memcpy( &headerLength, (uint8_t *)startCacheData + 0, 4 );
memcpy(&cacheHeaderVersion, (uint8_t *)startCacheData + 4, 4); memcpy( &cacheHeaderVersion, (uint8_t *)startCacheData + 4, 4 );
memcpy(&vendorID, (uint8_t *)startCacheData + 8, 4); memcpy( &vendorID, (uint8_t *)startCacheData + 8, 4 );
memcpy(&deviceID, (uint8_t *)startCacheData + 12, 4); memcpy( &deviceID, (uint8_t *)startCacheData + 12, 4 );
memcpy(pipelineCacheUUID, (uint8_t *)startCacheData + 16, VK_UUID_SIZE); memcpy( pipelineCacheUUID, (uint8_t *)startCacheData + 16, VK_UUID_SIZE );
// Check each field and report bad values before freeing existing cache // Check each field and report bad values before freeing existing cache
bool badCache = false; bool badCache = false;
if (headerLength <= 0) if ( headerLength <= 0 )
{ {
badCache = true; badCache = true;
std::cout << " Bad header length in " << cacheFileName << ".\n"; std::cout << " Bad header length in " << cacheFileName << ".\n";
std::cout << " Cache contains: " << std::hex << std::setw(8) << headerLength << "\n"; std::cout << " Cache contains: " << std::hex << std::setw( 8 ) << headerLength << "\n";
} }
if (cacheHeaderVersion != VK_PIPELINE_CACHE_HEADER_VERSION_ONE) if ( cacheHeaderVersion != VK_PIPELINE_CACHE_HEADER_VERSION_ONE )
{ {
badCache = true; badCache = true;
std::cout << " Unsupported cache header version in " << cacheFileName << ".\n"; std::cout << " Unsupported cache header version in " << cacheFileName << ".\n";
std::cout << " Cache contains: " << std::hex << std::setw(8) << cacheHeaderVersion << "\n"; std::cout << " Cache contains: " << std::hex << std::setw( 8 ) << cacheHeaderVersion << "\n";
} }
if (vendorID != properties.vendorID) if ( vendorID != properties.vendorID )
{ {
badCache = true; badCache = true;
std::cout << " Vender ID mismatch in " << cacheFileName << ".\n"; std::cout << " Vender ID mismatch in " << cacheFileName << ".\n";
std::cout << " Cache contains: " << std::hex << std::setw(8) << vendorID << "\n"; std::cout << " Cache contains: " << std::hex << std::setw( 8 ) << vendorID << "\n";
std::cout << " Driver expects: " << std::hex << std::setw(8) << properties.vendorID << "\n"; std::cout << " Driver expects: " << std::hex << std::setw( 8 ) << properties.vendorID << "\n";
} }
if (deviceID != properties.deviceID) if ( deviceID != properties.deviceID )
{ {
badCache = true; badCache = true;
std::cout << " Device ID mismatch in " << cacheFileName << ".\n"; std::cout << " Device ID mismatch in " << cacheFileName << ".\n";
std::cout << " Cache contains: " << std::hex << std::setw(8) << deviceID << "\n"; std::cout << " Cache contains: " << std::hex << std::setw( 8 ) << deviceID << "\n";
std::cout << " Driver expects: " << std::hex << std::setw(8) << properties.deviceID << "\n"; std::cout << " Driver expects: " << std::hex << std::setw( 8 ) << properties.deviceID << "\n";
} }
if (memcmp(pipelineCacheUUID, properties.pipelineCacheUUID, sizeof(pipelineCacheUUID)) != 0) if ( memcmp( pipelineCacheUUID, properties.pipelineCacheUUID, sizeof( pipelineCacheUUID ) ) != 0 )
{ {
badCache = true; badCache = true;
std::cout << " UUID mismatch in " << cacheFileName << ".\n"; std::cout << " UUID mismatch in " << cacheFileName << ".\n";
std::cout << " Cache contains: " << vk::su::UUID(pipelineCacheUUID) << "\n"; std::cout << " Cache contains: " << vk::su::UUID( pipelineCacheUUID ) << "\n";
std::cout << " Driver expects: " << vk::su::UUID(properties.pipelineCacheUUID) << "\n"; std::cout << " Driver expects: " << vk::su::UUID( properties.pipelineCacheUUID ) << "\n";
} }
if (badCache) if ( badCache )
{ {
// Don't submit initial cache data if any version info is incorrect // Don't submit initial cache data if any version info is incorrect
free(startCacheData); free( startCacheData );
startCacheSize = 0; startCacheSize = 0;
startCacheData = nullptr; startCacheData = nullptr;
// And clear out the old cache file for use in next run // And clear out the old cache file for use in next run
std::cout << " Deleting cache entry " << cacheFileName << " to repopulate.\n"; std::cout << " Deleting cache entry " << cacheFileName << " to repopulate.\n";
if (remove(cacheFileName.c_str()) != 0) if ( remove( cacheFileName.c_str() ) != 0 )
{ {
std::cerr << "Reading error"; std::cerr << "Reading error";
exit(EXIT_FAILURE); exit( EXIT_FAILURE );
} }
} }
} }
// Feed the initial cache data into cache creation // Feed the initial cache data into cache creation
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo(vk::PipelineCacheCreateFlags(), startCacheSize, startCacheData)); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(
vk::PipelineCacheCreateInfo( vk::PipelineCacheCreateFlags(), startCacheSize, startCacheData ) );
// Free our initialData now that pipeline cache has been created // Free our initialData now that pipeline cache has been created
free(startCacheData); free( startCacheData );
startCacheData = NULL; startCacheData = NULL;
// Time (roughly) taken to create the graphics pipeline // Time (roughly) taken to create the graphics pipeline
timestamp_t start = getMilliseconds(); timestamp_t start = getMilliseconds();
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline =
sizeof(texturedCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } }, vk::su::createGraphicsPipeline( device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( texturedCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
timestamp_t elapsed = getMilliseconds() - start; timestamp_t elapsed = getMilliseconds() - start;
std::cout << " vkCreateGraphicsPipeline time: " << (double)elapsed << " ms\n"; std::cout << " vkCreateGraphicsPipeline time: " << (double)elapsed << " ms\n";
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo(vk::SemaphoreCreateFlags())); vk::UniqueSemaphore imageAcquiredSemaphore =
device->createSemaphoreUnique( vk::SemaphoreCreateInfo( vk::SemaphoreCreateFlags() ) );
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer =
assert(currentBuffer.result == vk::Result::eSuccess); device->acquireNextImageKHR( swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
commandBuffer->beginRenderPass(vk::RenderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(), surfaceData.extent), 2, clearValues), vk::SubpassContents::eInline); commandBuffer->beginRenderPass( vk::RenderPassBeginInfo( renderPass.get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); framebuffers[currentBuffer.value].get(),
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), {}); vk::Rect2D( vk::Offset2D(), surfaceData.extent ),
2,
clearValues ),
vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), {} );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
// Store away the cache that we've populated. This could conceivably happen // Store away the cache that we've populated. This could conceivably happen
// earlier, depends on when the pipeline cache stops being populated // earlier, depends on when the pipeline cache stops being populated
// internally. // internally.
std::vector<uint8_t> endCacheData = device->getPipelineCacheData(pipelineCache.get()); std::vector<uint8_t> endCacheData = device->getPipelineCacheData( pipelineCache.get() );
// Write the file to disk, overwriting whatever was there // Write the file to disk, overwriting whatever was there
std::ofstream writeCacheStream(cacheFileName, std::ios_base::out | std::ios_base::binary); std::ofstream writeCacheStream( cacheFileName, std::ios_base::out | std::ios_base::binary );
if (writeCacheStream.good()) if ( writeCacheStream.good() )
{ {
writeCacheStream.write(reinterpret_cast<char const*>(endCacheData.data()), endCacheData.size()); writeCacheStream.write( reinterpret_cast<char const *>( endCacheData.data() ), endCacheData.size() );
writeCacheStream.close(); writeCacheStream.close();
std::cout << " cacheData written to " << cacheFileName << "\n"; std::cout << " cacheData written to " << cacheFileName << "\n";
} }
@ -318,20 +376,20 @@ int main(int /*argc*/, char ** /*argv*/)
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,69 +19,104 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <thread> #include <thread>
static char const* AppName = "PipelineDerivative"; static char const * AppName = "PipelineDerivative";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::TextureData textureData(physicalDevice, device); vk::su::TextureData textureData( physicalDevice, device );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
textureData.setImage(device, commandBuffer, vk::su::CheckerboardImageGenerator()); textureData.setImage( device, commandBuffer, vk::su::CheckerboardImageGenerator() );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
{ {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex}, {vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment} }); device,
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex },
{ vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, { {vk::DescriptorType::eUniformBuffer, 1}, {vk::DescriptorType::eCombinedImageSampler, 1} }); vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); device, { { vk::DescriptorType::eUniformBuffer, 1 }, { vk::DescriptorType::eCombinedImageSampler, 1 } } );
vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::su::updateDescriptorSets(device, descriptorSet, {{vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView()}}, textureData); vk::su::updateDescriptorSets(
device,
descriptorSet,
{ { vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView() } },
textureData );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
@ -90,43 +125,96 @@ int main(int /*argc*/, char ** /*argv*/)
// First pipeline has VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT set. // First pipeline has VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT set.
// Second pipeline has a modified fragment shader and sets the VK_PIPELINE_CREATE_DERIVATIVE_BIT flag. // Second pipeline has a modified fragment shader and sets the VK_PIPELINE_CREATE_DERIVATIVE_BIT flag.
vk::PipelineShaderStageCreateInfo pipelineShaderStageCreateInfos[2] = vk::PipelineShaderStageCreateInfo pipelineShaderStageCreateInfos[2] = {
{ vk::PipelineShaderStageCreateInfo(
vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, vertexShaderModule.get(), "main"), vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, vertexShaderModule.get(), "main" ),
vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule.get(), "main") vk::PipelineShaderStageCreateInfo(
vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule.get(), "main" )
}; };
vk::VertexInputBindingDescription vertexInputBindingDescription(0, sizeof(texturedCubeData[0])); vk::VertexInputBindingDescription vertexInputBindingDescription( 0, sizeof( texturedCubeData[0] ) );
vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[2] = vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
{ vk::VertexInputAttributeDescription( 0, 0, vk::Format::eR32G32B32A32Sfloat, 0 ),
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32A32Sfloat, 0), vk::VertexInputAttributeDescription( 1, 0, vk::Format::eR32G32B32A32Sfloat, 16 )
vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32A32Sfloat, 16)
}; };
vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(vk::PipelineVertexInputStateCreateFlags(), 1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions); vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(
vk::PipelineVertexInputStateCreateFlags(),
1,
&vertexInputBindingDescription,
2,
vertexInputAttributeDescriptions );
vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleList); vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(
vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleList );
vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(vk::PipelineViewportStateCreateFlags(), 1, nullptr, 1, nullptr); vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo(
vk::PipelineViewportStateCreateFlags(), 1, nullptr, 1, nullptr );
vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo(vk::PipelineRasterizationStateCreateFlags(), false, false, vk::PolygonMode::eFill, vk::CullModeFlagBits::eBack, vk::FrontFace::eClockwise, false, 0.0f, 0.0f, 0.0f, 1.0f); vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo(
vk::PipelineRasterizationStateCreateFlags(),
false,
false,
vk::PolygonMode::eFill,
vk::CullModeFlagBits::eBack,
vk::FrontFace::eClockwise,
false,
0.0f,
0.0f,
0.0f,
1.0f );
vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo({}, vk::SampleCountFlagBits::e1); vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo( {}, vk::SampleCountFlagBits::e1 );
vk::StencilOpState stencilOpState(vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways); vk::StencilOpState stencilOpState(
vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo(vk::PipelineDepthStencilStateCreateFlags(), true, true, vk::CompareOp::eLessOrEqual, false, false, stencilOpState, stencilOpState); vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::StencilOp::eKeep, vk::CompareOp::eAlways );
vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo(
vk::PipelineDepthStencilStateCreateFlags(),
true,
true,
vk::CompareOp::eLessOrEqual,
false,
false,
stencilOpState,
stencilOpState );
vk::ColorComponentFlags colorComponentFlags(vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA); vk::ColorComponentFlags colorComponentFlags( vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState(false, vk::BlendFactor::eZero, vk::BlendFactor::eZero, vk::BlendOp::eAdd, vk::BlendFactor::eZero, vk::BlendFactor::eZero, vk::BlendOp::eAdd, colorComponentFlags); vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA );
vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo(vk::PipelineColorBlendStateCreateFlags(), false, vk::LogicOp::eNoOp, 1, &pipelineColorBlendAttachmentState, { { 1.0f, 1.0f, 1.0f, 1.0f } }); vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState( false,
vk::BlendFactor::eZero,
vk::BlendFactor::eZero,
vk::BlendOp::eAdd,
vk::BlendFactor::eZero,
vk::BlendFactor::eZero,
vk::BlendOp::eAdd,
colorComponentFlags );
vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo( vk::PipelineColorBlendStateCreateFlags(),
false,
vk::LogicOp::eNoOp,
1,
&pipelineColorBlendAttachmentState,
{ { 1.0f, 1.0f, 1.0f, 1.0f } } );
vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; vk::DynamicState dynamicStates[2] = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates); vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo(
vk::PipelineDynamicStateCreateFlags(), 2, dynamicStates );
vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo(vk::PipelineCreateFlagBits::eAllowDerivatives, 2, pipelineShaderStageCreateInfos, &pipelineVertexInputStateCreateInfo, vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( vk::PipelineCreateFlagBits::eAllowDerivatives,
&pipelineInputAssemblyStateCreateInfo, nullptr, &pipelineViewportStateCreateInfo, &pipelineRasterizationStateCreateInfo, &pipelineMultisampleStateCreateInfo, 2,
&pipelineDepthStencilStateCreateInfo, &pipelineColorBlendStateCreateInfo, &pipelineDynamicStateCreateInfo, pipelineLayout.get(), renderPass.get()); pipelineShaderStageCreateInfos,
&pipelineVertexInputStateCreateInfo,
&pipelineInputAssemblyStateCreateInfo,
nullptr,
&pipelineViewportStateCreateInfo,
&pipelineRasterizationStateCreateInfo,
&pipelineMultisampleStateCreateInfo,
&pipelineDepthStencilStateCreateInfo,
&pipelineColorBlendStateCreateInfo,
&pipelineDynamicStateCreateInfo,
pipelineLayout.get(),
renderPass.get() );
vk::UniquePipeline basePipeline = device->createGraphicsPipelineUnique(pipelineCache.get(), graphicsPipelineCreateInfo); vk::UniquePipeline basePipeline =
device->createGraphicsPipelineUnique( pipelineCache.get(), graphicsPipelineCreateInfo );
// Now create the derivative pipeline, using a different fragment shader // Now create the derivative pipeline, using a different fragment shader
// This shader will shade the cube faces with interpolated colors // This shader will shade the cube faces with interpolated colors
@ -145,69 +233,87 @@ void main()
// Convert GLSL to SPIR-V // Convert GLSL to SPIR-V
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule fragmentShaderModule2 = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C_2); vk::UniqueShaderModule fragmentShaderModule2 =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C_2 );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
// Modify pipeline info to reflect derivation // Modify pipeline info to reflect derivation
pipelineShaderStageCreateInfos[1] = vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule2.get(), "main"); pipelineShaderStageCreateInfos[1] = vk::PipelineShaderStageCreateInfo(
graphicsPipelineCreateInfo.flags = vk::PipelineCreateFlagBits::eDerivative; vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule2.get(), "main" );
graphicsPipelineCreateInfo.flags = vk::PipelineCreateFlagBits::eDerivative;
graphicsPipelineCreateInfo.basePipelineHandle = basePipeline.get(); graphicsPipelineCreateInfo.basePipelineHandle = basePipeline.get();
graphicsPipelineCreateInfo.basePipelineIndex = -1; graphicsPipelineCreateInfo.basePipelineIndex = -1;
// And create the derived pipeline // And create the derived pipeline
vk::UniquePipeline derivedPipeline = device->createGraphicsPipelineUnique(pipelineCache.get(), graphicsPipelineCreateInfo); vk::UniquePipeline derivedPipeline =
device->createGraphicsPipelineUnique( pipelineCache.get(), graphicsPipelineCreateInfo );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo(vk::SemaphoreCreateFlags())); vk::UniqueSemaphore imageAcquiredSemaphore =
device->createSemaphoreUnique( vk::SemaphoreCreateInfo( vk::SemaphoreCreateFlags() ) );
// Get the index of the next available swapchain image // Get the index of the next available swapchain image
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer =
assert(currentBuffer.result == vk::Result::eSuccess); device->acquireNextImageKHR( swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
commandBuffer->beginRenderPass(vk::RenderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(), surfaceData.extent), 2, clearValues), vk::SubpassContents::eInline); commandBuffer->beginRenderPass( vk::RenderPassBeginInfo( renderPass.get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, derivedPipeline.get()); framebuffers[currentBuffer.value].get(),
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), {}); vk::Rect2D( vk::Offset2D(), surfaceData.extent ),
2,
clearValues ),
vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, derivedPipeline.get() );
commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), {} );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,13 +19,14 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "PushConstants"; static char const * AppName = "PushConstants";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
const std::string fragmentShaderText = R"( const std::string fragmentShaderText = R"(
#version 400 #version 400
@ -68,136 +69,186 @@ void main()
} }
)"; )";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
// Create binding and layout for the following, matching contents of shader // Create binding and layout for the following, matching contents of shader
// binding 0 = uniform buffer (MVP) // binding 0 = uniform buffer (MVP)
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, { {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex} }); vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
device, { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex } } );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Set up our push constant range, which mirrors the declaration of // Set up our push constant range, which mirrors the declaration of
vk::PushConstantRange pushConstantRanges(vk::ShaderStageFlagBits::eFragment, 0, 8); vk::PushConstantRange pushConstantRanges( vk::ShaderStageFlagBits::eFragment, 0, 8 );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get(), 1, &pushConstantRanges)); vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique( vk::PipelineLayoutCreateInfo(
vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get(), 1, &pushConstantRanges ) );
// Create a single pool to contain data for our descriptor set // Create a single pool to contain data for our descriptor set
vk::DescriptorPoolSize poolSizes[2] = vk::DescriptorPoolSize poolSizes[2] = { vk::DescriptorPoolSize( vk::DescriptorType::eUniformBuffer, 1 ),
{ vk::DescriptorPoolSize( vk::DescriptorType::eCombinedImageSampler, 1 ) };
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1), vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(
vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, 1) vk::DescriptorPoolCreateInfo( vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 2, poolSizes ) );
};
vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 2, poolSizes));
// Populate descriptor sets // Populate descriptor sets
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
// Populate with info about our uniform buffer for MVP // Populate with info about our uniform buffer for MVP
vk::DescriptorBufferInfo bufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); vk::DescriptorBufferInfo bufferInfo( uniformBufferData.buffer.get(), 0, sizeof( glm::mat4x4 ) );
device->updateDescriptorSets(vk::WriteDescriptorSet(*descriptorSet, 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo), {}); device->updateDescriptorSets(
vk::WriteDescriptorSet( *descriptorSet, 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo ), {} );
// Create our push constant data, which matches shader expectations // Create our push constant data, which matches shader expectations
std::array<unsigned, 2> pushConstants = { (unsigned)2, (unsigned)0x3F800000 }; std::array<unsigned, 2> pushConstants = { (unsigned)2, (unsigned)0x3F800000 };
// Ensure we have enough room for push constant data // Ensure we have enough room for push constant data
assert((sizeof(pushConstants) <= physicalDevice.getProperties().limits.maxPushConstantsSize) && "Too many push constants"); assert( ( sizeof( pushConstants ) <= physicalDevice.getProperties().limits.maxPushConstantsSize ) &&
commandBuffer->begin(vk::CommandBufferBeginInfo()); "Too many push constants" );
commandBuffer->pushConstants<unsigned>(pipelineLayout.get(), vk::ShaderStageFlagBits::eFragment, 0, pushConstants); commandBuffer->begin( vk::CommandBufferBeginInfo() );
commandBuffer->pushConstants<unsigned>(
pipelineLayout.get(), vk::ShaderStageFlagBits::eFragment, 0, pushConstants );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(
sizeof(texturedCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32B32A32Sfloat, 16 } }, device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( texturedCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32B32A32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); framebuffers[currentBuffer.value].get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr); 2,
clearValues );
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,164 +19,219 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "PushDescriptors"; static char const * AppName = "PushDescriptors";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
#if (VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1) #if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
// initialize the DipatchLoaderDynamic to use // initialize the DipatchLoaderDynamic to use
static vk::DynamicLoader dl; static vk::DynamicLoader dl;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); dl.getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" );
VULKAN_HPP_DEFAULT_DISPATCHER.init( vkGetInstanceProcAddr );
#endif #endif
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// To use PUSH_DESCRIPTOR, you must also specify GET_PHYSICAL_DEVICE_PROPERTIES_2 // To use PUSH_DESCRIPTOR, you must also specify GET_PHYSICAL_DEVICE_PROPERTIES_2
std::vector<vk::ExtensionProperties> extensionProperties = vk::enumerateInstanceExtensionProperties(); std::vector<vk::ExtensionProperties> extensionProperties = vk::enumerateInstanceExtensionProperties();
if (std::find_if(extensionProperties.begin(), extensionProperties.end(), [](vk::ExtensionProperties ep) { return (strcmp(ep.extensionName,VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0); }) == extensionProperties.end()) if ( std::find_if( extensionProperties.begin(), extensionProperties.end(), []( vk::ExtensionProperties ep ) {
return ( strcmp( ep.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME ) == 0 );
} ) == extensionProperties.end() )
{ {
std::cout << "No GET_PHYSICAL_DEVICE_PROPERTIES_2 extension" << std::endl; std::cout << "No GET_PHYSICAL_DEVICE_PROPERTIES_2 extension" << std::endl;
return 0; return 0;
} }
std::vector<std::string> instanceExtensions = vk::su::getInstanceExtensions(); std::vector<std::string> instanceExtensions = vk::su::getInstanceExtensions();
instanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); instanceExtensions.push_back( VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME );
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, instanceExtensions); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, instanceExtensions );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
// Once instance is created, need to make sure the extension is available // Once instance is created, need to make sure the extension is available
extensionProperties = physicalDevice.enumerateDeviceExtensionProperties(); extensionProperties = physicalDevice.enumerateDeviceExtensionProperties();
if (std::find_if(extensionProperties.begin(), extensionProperties.end(), [](vk::ExtensionProperties ep) { return (strcmp(ep.extensionName,VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME) == 0); }) == extensionProperties.end()) if ( std::find_if( extensionProperties.begin(), extensionProperties.end(), []( vk::ExtensionProperties ep ) {
return ( strcmp( ep.extensionName, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME ) == 0 );
} ) == extensionProperties.end() )
{ {
std::cout << "No extension for push descriptors" << std::endl; std::cout << "No extension for push descriptors" << std::endl;
return 0; return 0;
} }
std::vector<std::string> deviceExtensions = vk::su::getDeviceExtensions(); std::vector<std::string> deviceExtensions = vk::su::getDeviceExtensions();
deviceExtensions.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); deviceExtensions.push_back( VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME );
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, deviceExtensions); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, deviceExtensions );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::TextureData textureData(physicalDevice, device); vk::su::TextureData textureData( physicalDevice, device );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
textureData.setImage(device, commandBuffer, vk::su::CheckerboardImageGenerator()); textureData.setImage( device, commandBuffer, vk::su::CheckerboardImageGenerator() );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
// Need to specify that descriptor set layout will be for push descriptors // Need to specify that descriptor set layout will be for push descriptors
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
{ {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex}, {vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment} }, device,
vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR); { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex },
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); { vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment } },
vk::DescriptorSetLayoutCreateFlagBits::ePushDescriptorKHR );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline =
sizeof(texturedCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } }, vk::su::createGraphicsPipeline( device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( texturedCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); framebuffers[currentBuffer.value].get(),
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
2,
clearValues );
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
vk::DescriptorBufferInfo bufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); vk::DescriptorBufferInfo bufferInfo( uniformBufferData.buffer.get(), 0, sizeof( glm::mat4x4 ) );
vk::DescriptorImageInfo imageInfo(textureData.textureSampler.get(), textureData.imageData->imageView.get(), vk::ImageLayout::eShaderReadOnlyOptimal); vk::DescriptorImageInfo imageInfo( textureData.textureSampler.get(),
vk::WriteDescriptorSet writeDescriptorSets[2] = textureData.imageData->imageView.get(),
{ vk::ImageLayout::eShaderReadOnlyOptimal );
vk::WriteDescriptorSet({}, 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo), vk::WriteDescriptorSet writeDescriptorSets[2] = {
vk::WriteDescriptorSet({}, 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo) vk::WriteDescriptorSet( {}, 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo ),
vk::WriteDescriptorSet( {}, 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo )
}; };
// this call is from an extension and needs the dynamic dispatcher !! // this call is from an extension and needs the dynamic dispatcher !!
commandBuffer->pushDescriptorSetKHR(vk::PipelineBindPoint::eGraphics, *pipelineLayout, 0, {2, writeDescriptorSets}); commandBuffer->pushDescriptorSetKHR(
vk::PipelineBindPoint::eGraphics, *pipelineLayout, 0, { 2, writeDescriptorSets } );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -28,18 +28,18 @@ namespace vk
// MATH functions // MATH functions
// //
template <typename T> template <typename T>
bool isZero(const T& _a) bool isZero( const T & _a )
{ {
return fabs(_a) < std::numeric_limits<T>::epsilon(); return fabs( _a ) < std::numeric_limits<T>::epsilon();
} }
template <typename T> template <typename T>
bool isOne(const T& _a) bool isOne( const T & _a )
{ {
return areEqual(_a, (T)1); return areEqual( _a, (T)1 );
} }
inline float sign(float s) inline float sign( float s )
{ {
return (s < 0.f) ? -1.f : 1.f; return ( s < 0.f ) ? -1.f : 1.f;
} }
CameraManipulator::CameraManipulator() CameraManipulator::CameraManipulator()
@ -47,17 +47,17 @@ namespace vk
update(); update();
} }
glm::vec3 const& CameraManipulator::getCameraPosition() const glm::vec3 const & CameraManipulator::getCameraPosition() const
{ {
return m_cameraPosition; return m_cameraPosition;
} }
glm::vec3 const& CameraManipulator::getCenterPosition() const glm::vec3 const & CameraManipulator::getCenterPosition() const
{ {
return m_centerPosition; return m_centerPosition;
} }
glm::mat4 const& CameraManipulator::getMatrix() const glm::mat4 const & CameraManipulator::getMatrix() const
{ {
return m_matrix; return m_matrix;
} }
@ -67,7 +67,7 @@ namespace vk
return m_mode; return m_mode;
} }
glm::ivec2 const& CameraManipulator::getMousePosition() const glm::ivec2 const & CameraManipulator::getMousePosition() const
{ {
return m_mousePosition; return m_mousePosition;
} }
@ -82,31 +82,33 @@ namespace vk
return m_speed; return m_speed;
} }
glm::vec3 const& CameraManipulator::getUpVector() const glm::vec3 const & CameraManipulator::getUpVector() const
{ {
return m_upVector; return m_upVector;
} }
glm::u32vec2 const& CameraManipulator::getWindowSize() const glm::u32vec2 const & CameraManipulator::getWindowSize() const
{ {
return m_windowSize; return m_windowSize;
} }
CameraManipulator::Action CameraManipulator::mouseMove(glm::ivec2 const& position, MouseButton mouseButton, ModifierFlags & modifiers) CameraManipulator::Action
CameraManipulator::mouseMove( glm::ivec2 const & position, MouseButton mouseButton, ModifierFlags & modifiers )
{ {
Action curAction = Action::None; Action curAction = Action::None;
switch (mouseButton) switch ( mouseButton )
{ {
case MouseButton::Left: case MouseButton::Left:
if (((modifiers & ModifierFlagBits::Ctrl) && (modifiers & ModifierFlagBits::Shift)) || (modifiers & ModifierFlagBits::Alt)) if ( ( ( modifiers & ModifierFlagBits::Ctrl ) && ( modifiers & ModifierFlagBits::Shift ) ) ||
( modifiers & ModifierFlagBits::Alt ) )
{ {
curAction = m_mode == Mode::Examine ? Action::LookAround : Action::Orbit; curAction = m_mode == Mode::Examine ? Action::LookAround : Action::Orbit;
} }
else if (modifiers & ModifierFlagBits::Shift) else if ( modifiers & ModifierFlagBits::Shift )
{ {
curAction = Action::Dolly; curAction = Action::Dolly;
} }
else if (modifiers & ModifierFlagBits::Ctrl) else if ( modifiers & ModifierFlagBits::Ctrl )
{ {
curAction = Action::Pan; curAction = Action::Pan;
} }
@ -115,89 +117,86 @@ namespace vk
curAction = m_mode == Mode::Examine ? Action::Orbit : Action::LookAround; curAction = m_mode == Mode::Examine ? Action::Orbit : Action::LookAround;
} }
break; break;
case MouseButton::Middle: case MouseButton::Middle: curAction = Action::Pan; break;
curAction = Action::Pan; case MouseButton::Right: curAction = Action::Dolly; break;
break; default: assert( false );
case MouseButton::Right:
curAction = Action::Dolly;
break;
default:
assert(false);
} }
assert(curAction != Action::None); assert( curAction != Action::None );
motion(position, curAction); motion( position, curAction );
return curAction; return curAction;
} }
void CameraManipulator::setLookat(const glm::vec3& cameraPosition, const glm::vec3& centerPosition, const glm::vec3& upVector) void CameraManipulator::setLookat( const glm::vec3 & cameraPosition,
const glm::vec3 & centerPosition,
const glm::vec3 & upVector )
{ {
m_cameraPosition = cameraPosition; m_cameraPosition = cameraPosition;
m_centerPosition = centerPosition; m_centerPosition = centerPosition;
m_upVector = upVector; m_upVector = upVector;
update(); update();
} }
void CameraManipulator::setMode(Mode mode) void CameraManipulator::setMode( Mode mode )
{ {
m_mode = mode; m_mode = mode;
} }
void CameraManipulator::setMousePosition(glm::ivec2 const& position) void CameraManipulator::setMousePosition( glm::ivec2 const & position )
{ {
m_mousePosition = position; m_mousePosition = position;
} }
void CameraManipulator::setRoll(float roll) void CameraManipulator::setRoll( float roll )
{ {
m_roll = roll; m_roll = roll;
update(); update();
} }
void CameraManipulator::setSpeed(float speed) void CameraManipulator::setSpeed( float speed )
{ {
m_speed = speed; m_speed = speed;
} }
void CameraManipulator::setWindowSize(glm::ivec2 const& size) void CameraManipulator::setWindowSize( glm::ivec2 const & size )
{ {
m_windowSize = size; m_windowSize = size;
} }
void CameraManipulator::wheel(int value) void CameraManipulator::wheel( int value )
{ {
float fValue = static_cast<float>(value); float fValue = static_cast<float>( value );
float dx = (fValue * abs(fValue)) / static_cast<float>(m_windowSize[0]); float dx = ( fValue * abs( fValue ) ) / static_cast<float>( m_windowSize[0] );
glm::vec3 z = m_cameraPosition - m_centerPosition; glm::vec3 z = m_cameraPosition - m_centerPosition;
float length = z.length() * 0.1f; float length = z.length() * 0.1f;
length = length < 0.001f ? 0.001f : length; length = length < 0.001f ? 0.001f : length;
dx *= m_speed; dx *= m_speed;
dolly(glm::vec2(dx, dx)); dolly( glm::vec2( dx, dx ) );
update(); update();
} }
void CameraManipulator::dolly(glm::vec2 const& delta) void CameraManipulator::dolly( glm::vec2 const & delta )
{ {
glm::vec3 z = m_centerPosition - m_cameraPosition; glm::vec3 z = m_centerPosition - m_cameraPosition;
float length = glm::length(z); float length = glm::length( z );
// We are at the point of interest, and don't know any direction, so do nothing! // We are at the point of interest, and don't know any direction, so do nothing!
if(isZero(length)) if ( isZero( length ) )
{ {
return; return;
} }
// Use the larger movement. // Use the larger movement.
float dd; float dd;
if(m_mode != Mode::Examine) if ( m_mode != Mode::Examine )
{ {
dd = -delta[1]; dd = -delta[1];
} }
else else
{ {
dd = fabs(delta[0]) > fabs(delta[1]) ? delta[0] : -delta[1]; dd = fabs( delta[0] ) > fabs( delta[1] ) ? delta[0] : -delta[1];
} }
float factor = m_speed * dd / length; float factor = m_speed * dd / length;
@ -208,7 +207,7 @@ namespace vk
factor *= length; factor *= length;
// Don't move to or through the point of interest. // Don't move to or through the point of interest.
if (1.0f <= factor) if ( 1.0f <= factor )
{ {
return; return;
} }
@ -216,9 +215,9 @@ namespace vk
z *= factor; z *= factor;
// Not going up // Not going up
if(m_mode == Mode::Walk) if ( m_mode == Mode::Walk )
{ {
if(m_upVector.y > m_upVector.z) if ( m_upVector.y > m_upVector.z )
{ {
z.y = 0; z.y = 0;
} }
@ -231,42 +230,39 @@ namespace vk
m_cameraPosition += z; m_cameraPosition += z;
// In fly mode, the interest moves with us. // In fly mode, the interest moves with us.
if(m_mode != Mode::Examine) if ( m_mode != Mode::Examine )
{ {
m_centerPosition += z; m_centerPosition += z;
} }
} }
void CameraManipulator::motion(glm::ivec2 const& position, Action action) void CameraManipulator::motion( glm::ivec2 const & position, Action action )
{ {
glm::vec2 delta(float(position[0] - m_mousePosition[0]) / float(m_windowSize[0]), float(position[1] - m_mousePosition[1]) / float(m_windowSize[1])); glm::vec2 delta( float( position[0] - m_mousePosition[0] ) / float( m_windowSize[0] ),
float( position[1] - m_mousePosition[1] ) / float( m_windowSize[1] ) );
switch(action) switch ( action )
{ {
case Action::Orbit: case Action::Orbit:
if(m_mode == Mode::Trackball) if ( m_mode == Mode::Trackball )
{ {
orbit(delta, true); // trackball(position); orbit( delta, true ); // trackball(position);
} }
else else
{ {
orbit(delta, false); orbit( delta, false );
} }
break; break;
case Action::Dolly: case Action::Dolly: dolly( delta ); break;
dolly(delta); case Action::Pan: pan( delta ); break;
break;
case Action::Pan:
pan(delta);
break;
case Action::LookAround: case Action::LookAround:
if(m_mode == Mode::Trackball) if ( m_mode == Mode::Trackball )
{ {
trackball(position); trackball( position );
} }
else else
{ {
orbit(glm::vec2(delta[0], -delta[1]), true); orbit( glm::vec2( delta[0], -delta[1] ), true );
} }
break; break;
} }
@ -276,43 +272,43 @@ namespace vk
m_mousePosition = position; m_mousePosition = position;
} }
void CameraManipulator::orbit(glm::vec2 const& delta, bool invert) void CameraManipulator::orbit( glm::vec2 const & delta, bool invert )
{ {
if(isZero(delta[0]) && isZero(delta[1])) if ( isZero( delta[0] ) && isZero( delta[1] ) )
{ {
return; return;
} }
// Full width will do a full turn // Full width will do a full turn
float dx = delta[0] * float(glm::two_pi<float>()); float dx = delta[0] * float( glm::two_pi<float>() );
float dy = delta[1] * float(glm::two_pi<float>()); float dy = delta[1] * float( glm::two_pi<float>() );
// Get the camera // Get the camera
glm::vec3 origin(invert ? m_cameraPosition : m_centerPosition); glm::vec3 origin( invert ? m_cameraPosition : m_centerPosition );
glm::vec3 position(invert ? m_centerPosition : m_cameraPosition); glm::vec3 position( invert ? m_centerPosition : m_cameraPosition );
// Get the length of sight // Get the length of sight
glm::vec3 centerToEye(position - origin); glm::vec3 centerToEye( position - origin );
float radius = glm::length(centerToEye); float radius = glm::length( centerToEye );
centerToEye = glm::normalize(centerToEye); centerToEye = glm::normalize( centerToEye );
// Find the rotation around the UP axis (Y) // Find the rotation around the UP axis (Y)
glm::vec3 zAxis(centerToEye); glm::vec3 zAxis( centerToEye );
glm::mat4 yRotation = glm::rotate(-dx, m_upVector); glm::mat4 yRotation = glm::rotate( -dx, m_upVector );
// Apply the (Y) rotation to the eye-center vector // Apply the (Y) rotation to the eye-center vector
glm::vec4 tmpVector = yRotation * glm::vec4(centerToEye.x, centerToEye.y, centerToEye.z, 0.0f); glm::vec4 tmpVector = yRotation * glm::vec4( centerToEye.x, centerToEye.y, centerToEye.z, 0.0f );
centerToEye = glm::vec3(tmpVector.x, tmpVector.y, tmpVector.z); centerToEye = glm::vec3( tmpVector.x, tmpVector.y, tmpVector.z );
// Find the rotation around the X vector: cross between eye-center and up (X) // Find the rotation around the X vector: cross between eye-center and up (X)
glm::vec3 xAxis = glm::cross(m_upVector, zAxis); glm::vec3 xAxis = glm::cross( m_upVector, zAxis );
xAxis = glm::normalize(xAxis); xAxis = glm::normalize( xAxis );
glm::mat4 xRotation = glm::rotate(-dy, xAxis); glm::mat4 xRotation = glm::rotate( -dy, xAxis );
// Apply the (X) rotation to the eye-center vector // Apply the (X) rotation to the eye-center vector
tmpVector = xRotation * glm::vec4(centerToEye.x, centerToEye.y, centerToEye.z, 0); tmpVector = xRotation * glm::vec4( centerToEye.x, centerToEye.y, centerToEye.z, 0 );
glm::vec3 rotatedVector(tmpVector.x, tmpVector.y, tmpVector.z); glm::vec3 rotatedVector( tmpVector.x, tmpVector.y, tmpVector.z );
if(sign(rotatedVector.x) == sign(centerToEye.x)) if ( sign( rotatedVector.x ) == sign( centerToEye.x ) )
{ {
centerToEye = rotatedVector; centerToEye = rotatedVector;
} }
@ -323,7 +319,7 @@ namespace vk
// Finding the new position // Finding the new position
glm::vec3 newPosition = centerToEye + origin; glm::vec3 newPosition = centerToEye + origin;
if(!invert) if ( !invert )
{ {
m_cameraPosition = newPosition; // Normal: change the position of the camera m_cameraPosition = newPosition; // Normal: change the position of the camera
} }
@ -333,17 +329,17 @@ namespace vk
} }
} }
void CameraManipulator::pan(glm::vec2 const& delta) void CameraManipulator::pan( glm::vec2 const & delta )
{ {
glm::vec3 z(m_cameraPosition - m_centerPosition); glm::vec3 z( m_cameraPosition - m_centerPosition );
float length = static_cast<float>(glm::length(z)) / 0.785f; // 45 degrees float length = static_cast<float>( glm::length( z ) ) / 0.785f; // 45 degrees
z = glm::normalize(z); z = glm::normalize( z );
glm::vec3 x = glm::normalize(glm::cross(m_upVector, z)); glm::vec3 x = glm::normalize( glm::cross( m_upVector, z ) );
glm::vec3 y = glm::normalize(glm::cross(z, x)); glm::vec3 y = glm::normalize( glm::cross( z, x ) );
x *= -delta[0] * length; x *= -delta[0] * length;
y *= delta[1] * length; y *= delta[1] * length;
if(m_mode == Mode::Fly) if ( m_mode == Mode::Fly )
{ {
x = -x; x = -x;
y = -y; y = -y;
@ -353,14 +349,14 @@ namespace vk
m_centerPosition += x + y; m_centerPosition += x + y;
} }
double CameraManipulator::projectOntoTBSphere(const glm::vec2& p) double CameraManipulator::projectOntoTBSphere( const glm::vec2 & p )
{ {
double z; double z;
double d = length(p); double d = length( p );
if(d < trackballSize * 0.70710678118654752440) if ( d < trackballSize * 0.70710678118654752440 )
{ {
// inside sphere // inside sphere
z = sqrt(trackballSize * trackballSize - d * d); z = sqrt( trackballSize * trackballSize - d * d );
} }
else else
{ {
@ -372,57 +368,58 @@ namespace vk
return z; return z;
} }
void CameraManipulator::trackball(glm::ivec2 const& position) void CameraManipulator::trackball( glm::ivec2 const & position )
{ {
glm::vec2 p0(2 * (m_mousePosition[0] - m_windowSize[0] / 2) / double(m_windowSize[0]), glm::vec2 p0( 2 * ( m_mousePosition[0] - m_windowSize[0] / 2 ) / double( m_windowSize[0] ),
2 * (m_windowSize[1] / 2 - m_mousePosition[1]) / double(m_windowSize[1])); 2 * ( m_windowSize[1] / 2 - m_mousePosition[1] ) / double( m_windowSize[1] ) );
glm::vec2 p1(2 * (position[0] - m_windowSize[0] / 2) / double(m_windowSize[0]), 2 * (m_windowSize[1] / 2 - position[1]) / double(m_windowSize[1])); glm::vec2 p1( 2 * ( position[0] - m_windowSize[0] / 2 ) / double( m_windowSize[0] ),
2 * ( m_windowSize[1] / 2 - position[1] ) / double( m_windowSize[1] ) );
// determine the z coordinate on the sphere // determine the z coordinate on the sphere
glm::vec3 pTB0(p0[0], p0[1], projectOntoTBSphere(p0)); glm::vec3 pTB0( p0[0], p0[1], projectOntoTBSphere( p0 ) );
glm::vec3 pTB1(p1[0], p1[1], projectOntoTBSphere(p1)); glm::vec3 pTB1( p1[0], p1[1], projectOntoTBSphere( p1 ) );
// calculate the rotation axis via cross product between p0 and p1 // calculate the rotation axis via cross product between p0 and p1
glm::vec3 axis = glm::cross(pTB0, pTB1); glm::vec3 axis = glm::cross( pTB0, pTB1 );
axis = glm::normalize(axis); axis = glm::normalize( axis );
// calculate the angle // calculate the angle
float t = glm::length(pTB0 - pTB1) / (2.f * trackballSize); float t = glm::length( pTB0 - pTB1 ) / ( 2.f * trackballSize );
// clamp between -1 and 1 // clamp between -1 and 1
if(t > 1.0f) if ( t > 1.0f )
{ {
t = 1.0f; t = 1.0f;
} }
else if(t < -1.0f) else if ( t < -1.0f )
{ {
t = -1.0f; t = -1.0f;
} }
float rad = 2.0f * asin(t); float rad = 2.0f * asin( t );
{ {
glm::vec4 rot_axis = m_matrix * glm::vec4(axis, 0); glm::vec4 rot_axis = m_matrix * glm::vec4( axis, 0 );
glm::mat4 rot_mat = glm::rotate(rad, glm::vec3(rot_axis.x, rot_axis.y, rot_axis.z)); glm::mat4 rot_mat = glm::rotate( rad, glm::vec3( rot_axis.x, rot_axis.y, rot_axis.z ) );
glm::vec3 pnt = m_cameraPosition - m_centerPosition; glm::vec3 pnt = m_cameraPosition - m_centerPosition;
glm::vec4 pnt2 = rot_mat * glm::vec4(pnt.x, pnt.y, pnt.z, 1); glm::vec4 pnt2 = rot_mat * glm::vec4( pnt.x, pnt.y, pnt.z, 1 );
m_cameraPosition = m_centerPosition + glm::vec3(pnt2.x, pnt2.y, pnt2.z); m_cameraPosition = m_centerPosition + glm::vec3( pnt2.x, pnt2.y, pnt2.z );
glm::vec4 up2 = rot_mat * glm::vec4(m_upVector.x, m_upVector.y, m_upVector.z, 0); glm::vec4 up2 = rot_mat * glm::vec4( m_upVector.x, m_upVector.y, m_upVector.z, 0 );
m_upVector = glm::vec3(up2.x, up2.y, up2.z); m_upVector = glm::vec3( up2.x, up2.y, up2.z );
} }
} }
void CameraManipulator::update() void CameraManipulator::update()
{ {
m_matrix = glm::lookAt(m_cameraPosition, m_centerPosition, m_upVector); m_matrix = glm::lookAt( m_cameraPosition, m_centerPosition, m_upVector );
if(!isZero(m_roll)) if ( !isZero( m_roll ) )
{ {
glm::mat4 rot = glm::rotate(m_roll, glm::vec3(0, 0, 1)); glm::mat4 rot = glm::rotate( m_roll, glm::vec3( 0, 0, 1 ) );
m_matrix = m_matrix * rot; m_matrix = m_matrix * rot;
} }
} }
} // namespace su } // namespace su
} // namespace vk } // namespace vk

File diff suppressed because it is too large Load Diff

View File

@ -19,167 +19,241 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "SecondaryCommandBuffer"; static char const * AppName = "SecondaryCommandBuffer";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
{ {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex}, {vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment} }); device,
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex },
{ vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format, vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
vk::AttachmentLoadOp::eClear, vk::ImageLayout::eColorAttachmentOptimal); device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format,
vk::AttachmentLoadOp::eClear,
vk::ImageLayout::eColorAttachmentOptimal );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline =
sizeof(texturedCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } }, vk::su::createGraphicsPipeline( device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( texturedCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
vk::su::TextureData greenTextureData(physicalDevice, device); vk::su::TextureData greenTextureData( physicalDevice, device );
greenTextureData.setImage(device, commandBuffer, vk::su::MonochromeImageGenerator({ 118, 185, 0 })); greenTextureData.setImage( device, commandBuffer, vk::su::MonochromeImageGenerator( { 118, 185, 0 } ) );
vk::su::TextureData checkeredTextureData(physicalDevice, device); vk::su::TextureData checkeredTextureData( physicalDevice, device );
checkeredTextureData.setImage(device, commandBuffer, vk::su::CheckerboardImageGenerator()); checkeredTextureData.setImage( device, commandBuffer, vk::su::CheckerboardImageGenerator() );
// create two identical descriptor sets, each with a different texture but identical UBOs // create two identical descriptor sets, each with a different texture but identical UBOs
vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, { {vk::DescriptorType::eUniformBuffer, 2}, {vk::DescriptorType::eCombinedImageSampler, 2} }); vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(
device, { { vk::DescriptorType::eUniformBuffer, 2 }, { vk::DescriptorType::eCombinedImageSampler, 2 } } );
vk::DescriptorSetLayout layouts[] = { descriptorSetLayout.get(), descriptorSetLayout.get() }; vk::DescriptorSetLayout layouts[] = { descriptorSetLayout.get(), descriptorSetLayout.get() };
std::vector<vk::UniqueDescriptorSet> descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 2, layouts)); std::vector<vk::UniqueDescriptorSet> descriptorSets =
assert(descriptorSets.size() == 2); device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( descriptorPool.get(), 2, layouts ) );
assert( descriptorSets.size() == 2 );
vk::su::updateDescriptorSets(device, descriptorSets[0], {{vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView()}}, greenTextureData); vk::su::updateDescriptorSets(
vk::su::updateDescriptorSets(device, descriptorSets[1], {{vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView()}}, checkeredTextureData); device,
descriptorSets[0],
{ { vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView() } },
greenTextureData );
vk::su::updateDescriptorSets(
device,
descriptorSets[1],
{ { vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView() } },
checkeredTextureData );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// create four secondary command buffers, for each quadrant of the screen // create four secondary command buffers, for each quadrant of the screen
std::vector<vk::UniqueCommandBuffer> secondaryCommandBuffers = device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::eSecondary, 4)); std::vector<vk::UniqueCommandBuffer> secondaryCommandBuffers = device->allocateCommandBuffersUnique(
vk::CommandBufferAllocateInfo( commandPool.get(), vk::CommandBufferLevel::eSecondary, 4 ) );
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::su::setImageLayout(commandBuffer, swapChainData.images[currentBuffer.value], swapChainData.colorFormat, vk::ImageLayout::eUndefined, vk::ImageLayout::eColorAttachmentOptimal); vk::su::setImageLayout( commandBuffer,
swapChainData.images[currentBuffer.value],
swapChainData.colorFormat,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eColorAttachmentOptimal );
const vk::DeviceSize offset = 0; const vk::DeviceSize offset = 0;
vk::Viewport viewport(0.0f, 0.0f, 200.0f, 200.0f, 0.0f, 1.0f); vk::Viewport viewport( 0.0f, 0.0f, 200.0f, 200.0f, 0.0f, 1.0f );
vk::Rect2D scissor(vk::Offset2D(0, 0), vk::Extent2D(surfaceData.extent)); vk::Rect2D scissor( vk::Offset2D( 0, 0 ), vk::Extent2D( surfaceData.extent ) );
// now we record four separate command buffers, one for each quadrant of the screen // now we record four separate command buffers, one for each quadrant of the screen
vk::CommandBufferInheritanceInfo commandBufferInheritanceInfo(renderPass.get(), 0, framebuffers[currentBuffer.value].get()); vk::CommandBufferInheritanceInfo commandBufferInheritanceInfo(
vk::CommandBufferBeginInfo secondaryBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit | vk::CommandBufferUsageFlagBits::eRenderPassContinue, &commandBufferInheritanceInfo); renderPass.get(), 0, framebuffers[currentBuffer.value].get() );
vk::CommandBufferBeginInfo secondaryBeginInfo( vk::CommandBufferUsageFlagBits::eOneTimeSubmit |
vk::CommandBufferUsageFlagBits::eRenderPassContinue,
&commandBufferInheritanceInfo );
for (int i = 0; i < 4; i++) for ( int i = 0; i < 4; i++ )
{ {
viewport.x = 25.0f + 250.0f * (i % 2); viewport.x = 25.0f + 250.0f * ( i % 2 );
viewport.y = 25.0f + 250.0f * (i / 2); viewport.y = 25.0f + 250.0f * ( i / 2 );
secondaryCommandBuffers[i]->begin(secondaryBeginInfo); secondaryCommandBuffers[i]->begin( secondaryBeginInfo );
secondaryCommandBuffers[i]->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); secondaryCommandBuffers[i]->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
secondaryCommandBuffers[i]->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSets[i == 0 || i == 3].get(), nullptr); secondaryCommandBuffers[i]->bindDescriptorSets(
secondaryCommandBuffers[i]->bindVertexBuffers(0, vertexBufferData.buffer.get(), offset); vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSets[i == 0 || i == 3].get(), nullptr );
secondaryCommandBuffers[i]->setViewport(0, viewport); secondaryCommandBuffers[i]->bindVertexBuffers( 0, vertexBufferData.buffer.get(), offset );
secondaryCommandBuffers[i]->setScissor(0, scissor); secondaryCommandBuffers[i]->setViewport( 0, viewport );
secondaryCommandBuffers[i]->draw(12 * 3, 1, 0, 0); secondaryCommandBuffers[i]->setScissor( 0, scissor );
secondaryCommandBuffers[i]->draw( 12 * 3, 1, 0, 0 );
secondaryCommandBuffers[i]->end(); secondaryCommandBuffers[i]->end();
} }
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
// specifying VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS means this render pass may ONLY call vkCmdExecuteCommands framebuffers[currentBuffer.value].get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eSecondaryCommandBuffers); vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
commandBuffer->executeCommands(vk::uniqueToRaw(secondaryCommandBuffers)); 2,
clearValues );
// specifying VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS means this render pass may ONLY call
// vkCmdExecuteCommands
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eSecondaryCommandBuffers );
commandBuffer->executeCommands( vk::uniqueToRaw( secondaryCommandBuffers ) );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
vk::ImageMemoryBarrier prePresentBarrier(vk::AccessFlagBits::eColorAttachmentWrite, vk::AccessFlagBits::eMemoryRead, vk::ImageLayout::eColorAttachmentOptimal, vk::ImageLayout::ePresentSrcKHR, vk::ImageMemoryBarrier prePresentBarrier(
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, swapChainData.images[currentBuffer.value], vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1)); vk::AccessFlagBits::eColorAttachmentWrite,
commandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eBottomOfPipe, vk::DependencyFlags(), nullptr, nullptr, prePresentBarrier); vk::AccessFlagBits::eMemoryRead,
vk::ImageLayout::eColorAttachmentOptimal,
vk::ImageLayout::ePresentSrcKHR,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
swapChainData.images[currentBuffer.value],
vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 ) );
commandBuffer->pipelineBarrier( vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eBottomOfPipe,
vk::DependencyFlags(),
nullptr,
nullptr,
prePresentBarrier );
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,13 +19,14 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "SeparateImageSampler"; static char const * AppName = "SeparateImageSampler";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
const std::string fragmentShaderTextTS_T_C = R"( const std::string fragmentShaderTextTS_T_C = R"(
#version 400 #version 400
@ -56,164 +57,225 @@ void main()
} }
)"; )";
int main( int /*argc*/, char ** /*argv*/ )
int main(int /*argc*/, char ** /*argv*/)
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format, vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
vk::AttachmentLoadOp::eClear); device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format,
vk::AttachmentLoadOp::eClear );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderTextTS_T_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderTextTS_T_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
// Create the separate image // Create the separate image
vk::su::TextureData textureData(physicalDevice, device); vk::su::TextureData textureData( physicalDevice, device );
textureData.setImage(device, commandBuffer, vk::su::MonochromeImageGenerator({ 118, 185, 0 })); textureData.setImage( device, commandBuffer, vk::su::MonochromeImageGenerator( { 118, 185, 0 } ) );
// Create the separate sampler // Create the separate sampler
vk::UniqueSampler sampler = device->createSamplerUnique(vk::SamplerCreateInfo(vk::SamplerCreateFlags(), vk::Filter::eNearest, vk::Filter::eNearest, vk::SamplerMipmapMode::eNearest, vk::UniqueSampler sampler =
vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, device->createSamplerUnique( vk::SamplerCreateInfo( vk::SamplerCreateFlags(),
0.0f, false, 1.0f, false, vk::CompareOp::eNever, 0.0f, 0.0f, vk::BorderColor::eFloatOpaqueWhite)); vk::Filter::eNearest,
vk::Filter::eNearest,
vk::SamplerMipmapMode::eNearest,
vk::SamplerAddressMode::eClampToEdge,
vk::SamplerAddressMode::eClampToEdge,
vk::SamplerAddressMode::eClampToEdge,
0.0f,
false,
1.0f,
false,
vk::CompareOp::eNever,
0.0f,
0.0f,
vk::BorderColor::eFloatOpaqueWhite ) );
// Create binding and layout for the following, matching contents of shader // Create binding and layout for the following, matching contents of shader
// binding 0 = uniform buffer (MVP) // binding 0 = uniform buffer (MVP)
// binding 1 = texture2D // binding 1 = texture2D
// binding 2 = sampler // binding 2 = sampler
std::array<vk::DescriptorSetLayoutBinding, 3> resourceBindings = std::array<vk::DescriptorSetLayoutBinding, 3> resourceBindings = {
{ vk::DescriptorSetLayoutBinding( 0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex ),
vk::DescriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex), vk::DescriptorSetLayoutBinding( 1, vk::DescriptorType::eSampledImage, 1, vk::ShaderStageFlagBits::eFragment ),
vk::DescriptorSetLayoutBinding(1, vk::DescriptorType::eSampledImage, 1, vk::ShaderStageFlagBits::eFragment), vk::DescriptorSetLayoutBinding( 2, vk::DescriptorType::eSampler, 1, vk::ShaderStageFlagBits::eFragment )
vk::DescriptorSetLayoutBinding(2, vk::DescriptorType::eSampler, 1, vk::ShaderStageFlagBits::eFragment)
}; };
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(
static_cast<uint32_t>(resourceBindings.size()), vk::DescriptorSetLayoutCreateInfo( vk::DescriptorSetLayoutCreateFlags(),
resourceBindings.data())); static_cast<uint32_t>( resourceBindings.size() ),
resourceBindings.data() ) );
// Create pipeline layout // Create pipeline layout
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &(*descriptorSetLayout))); vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &( *descriptorSetLayout ) ) );
// Create a single pool to contain data for the descriptor set // Create a single pool to contain data for the descriptor set
std::array<vk::DescriptorPoolSize, 3> poolSizes = std::array<vk::DescriptorPoolSize, 3> poolSizes = { vk::DescriptorPoolSize( vk::DescriptorType::eUniformBuffer, 1 ),
{ vk::DescriptorPoolSize( vk::DescriptorType::eSampledImage, 1 ),
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1), vk::DescriptorPoolSize( vk::DescriptorType::eSampler, 1 ) };
vk::DescriptorPoolSize(vk::DescriptorType::eSampledImage, 1), vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(
vk::DescriptorPoolSize(vk::DescriptorType::eSampler, 1) vk::DescriptorPoolCreateInfo( vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
}; 1,
vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, static_cast<uint32_t>( poolSizes.size() ),
static_cast<uint32_t>(poolSizes.size()), poolSizes.data())); poolSizes.data() ) );
// Populate descriptor sets // Populate descriptor sets
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::DescriptorBufferInfo bufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4)); vk::DescriptorBufferInfo bufferInfo( uniformBufferData.buffer.get(), 0, sizeof( glm::mat4x4 ) );
vk::DescriptorImageInfo imageInfo(textureData.textureSampler.get(), textureData.imageData->imageView.get(), vk::ImageLayout::eShaderReadOnlyOptimal); vk::DescriptorImageInfo imageInfo( textureData.textureSampler.get(),
vk::DescriptorImageInfo samplerInfo(sampler.get(), {}, {}); textureData.imageData->imageView.get(),
std::array<vk::WriteDescriptorSet,3> descriptorWrites = vk::ImageLayout::eShaderReadOnlyOptimal );
{ vk::DescriptorImageInfo samplerInfo( sampler.get(), {}, {} );
vk::WriteDescriptorSet(*descriptorSet, 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo), std::array<vk::WriteDescriptorSet, 3> descriptorWrites = {
vk::WriteDescriptorSet(*descriptorSet, 1, 0, 1, vk::DescriptorType::eSampledImage, &imageInfo), vk::WriteDescriptorSet( *descriptorSet, 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo ),
vk::WriteDescriptorSet(*descriptorSet, 2, 0, 1, vk::DescriptorType::eSampler, &samplerInfo) vk::WriteDescriptorSet( *descriptorSet, 1, 0, 1, vk::DescriptorType::eSampledImage, &imageInfo ),
vk::WriteDescriptorSet( *descriptorSet, 2, 0, 1, vk::DescriptorType::eSampler, &samplerInfo )
}; };
device->updateDescriptorSets(descriptorWrites, nullptr); device->updateDescriptorSets( descriptorWrites, nullptr );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline =
sizeof(texturedCubeData[0]), { { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } }, vk::su::createGraphicsPipeline( device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( texturedCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); framebuffers[currentBuffer.value].get(),
vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
2,
clearValues );
commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr); commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,132 +17,171 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
static char const* AppName = "SurfaceCapabilities"; static char const * AppName = "SurfaceCapabilities";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
void cout(vk::SurfaceCapabilitiesKHR const& surfaceCapabilities) void cout( vk::SurfaceCapabilitiesKHR const & surfaceCapabilities )
{ {
std::cout << "\tCapabilities:\n"; std::cout << "\tCapabilities:\n";
std::cout << "\t\t" << "currentExtent = " << surfaceCapabilities.currentExtent.width << " x " << surfaceCapabilities.currentExtent.height << "\n"; std::cout << "\t\t"
std::cout << "\t\t" << "currentTransform = " << vk::to_string(surfaceCapabilities.currentTransform) << "\n"; << "currentExtent = " << surfaceCapabilities.currentExtent.width << " x "
std::cout << "\t\t" << "maxImageArrayLayers = " << surfaceCapabilities.maxImageArrayLayers << "\n"; << surfaceCapabilities.currentExtent.height << "\n";
std::cout << "\t\t" << "maxImageCount = " << surfaceCapabilities.maxImageCount << "\n"; std::cout << "\t\t"
std::cout << "\t\t" << "maxImageExtent = " << surfaceCapabilities.maxImageExtent.width << " x " << surfaceCapabilities.maxImageExtent.height << "\n"; << "currentTransform = " << vk::to_string( surfaceCapabilities.currentTransform ) << "\n";
std::cout << "\t\t" << "minImageCount = " << surfaceCapabilities.minImageCount << "\n"; std::cout << "\t\t"
std::cout << "\t\t" << "minImageExtent = " << surfaceCapabilities.minImageExtent.width << " x " << surfaceCapabilities.minImageExtent.height << "\n"; << "maxImageArrayLayers = " << surfaceCapabilities.maxImageArrayLayers << "\n";
std::cout << "\t\t" << "supportedCompositeAlpha = " << vk::to_string(surfaceCapabilities.supportedCompositeAlpha) << "\n"; std::cout << "\t\t"
std::cout << "\t\t" << "supportedTransforms = " << vk::to_string(surfaceCapabilities.supportedTransforms) << "\n"; << "maxImageCount = " << surfaceCapabilities.maxImageCount << "\n";
std::cout << "\t\t" << "supportedUsageFlags = " << vk::to_string(surfaceCapabilities.supportedUsageFlags) << "\n"; std::cout << "\t\t"
<< "maxImageExtent = " << surfaceCapabilities.maxImageExtent.width << " x "
<< surfaceCapabilities.maxImageExtent.height << "\n";
std::cout << "\t\t"
<< "minImageCount = " << surfaceCapabilities.minImageCount << "\n";
std::cout << "\t\t"
<< "minImageExtent = " << surfaceCapabilities.minImageExtent.width << " x "
<< surfaceCapabilities.minImageExtent.height << "\n";
std::cout << "\t\t"
<< "supportedCompositeAlpha = " << vk::to_string( surfaceCapabilities.supportedCompositeAlpha ) << "\n";
std::cout << "\t\t"
<< "supportedTransforms = " << vk::to_string( surfaceCapabilities.supportedTransforms ) << "\n";
std::cout << "\t\t"
<< "supportedUsageFlags = " << vk::to_string( surfaceCapabilities.supportedUsageFlags ) << "\n";
std::cout << "\n"; std::cout << "\n";
} }
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
// need to initialize the dynamic dispatcher before the very first vulkan call // need to initialize the dynamic dispatcher before the very first vulkan call
#if (VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1) #if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
static vk::DynamicLoader dl; static vk::DynamicLoader dl;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); dl.getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" );
VULKAN_HPP_DEFAULT_DISPATCHER.init( vkGetInstanceProcAddr );
#endif #endif
std::vector<vk::ExtensionProperties> instanceExtensionProperties = vk::enumerateInstanceExtensionProperties(); std::vector<vk::ExtensionProperties> instanceExtensionProperties = vk::enumerateInstanceExtensionProperties();
bool supportsGetSurfaceCapabilities2 = (std::find_if(instanceExtensionProperties.begin(), instanceExtensionProperties.end(), [](vk::ExtensionProperties const& ep) { return strcmp(ep.extensionName, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME) == 0; }) != instanceExtensionProperties.end()); bool supportsGetSurfaceCapabilities2 =
( std::find_if( instanceExtensionProperties.begin(),
instanceExtensionProperties.end(),
[]( vk::ExtensionProperties const & ep ) {
return strcmp( ep.extensionName, VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME ) == 0;
} ) != instanceExtensionProperties.end() );
std::vector<std::string> extensions = vk::su::getInstanceExtensions(); std::vector<std::string> extensions = vk::su::getInstanceExtensions();
if (supportsGetSurfaceCapabilities2) if ( supportsGetSurfaceCapabilities2 )
{ {
extensions.push_back(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME); extensions.push_back( VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME );
} }
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, extensions); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, extensions );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
// enumerate the physicalDevices // enumerate the physicalDevices
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices(); std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
std::cout << std::boolalpha; std::cout << std::boolalpha;
for (size_t i=0 ; i<physicalDevices.size() ; i++) for ( size_t i = 0; i < physicalDevices.size(); i++ )
{ {
// some properties are only valid, if a corresponding extension is available! // some properties are only valid, if a corresponding extension is available!
std::vector<vk::ExtensionProperties> extensionProperties = physicalDevices[i].enumerateDeviceExtensionProperties(); std::vector<vk::ExtensionProperties> extensionProperties =
physicalDevices[i].enumerateDeviceExtensionProperties();
std::cout << "PhysicalDevice " << i << "\n"; std::cout << "PhysicalDevice " << i << "\n";
if (supportsGetSurfaceCapabilities2) if ( supportsGetSurfaceCapabilities2 )
{ {
auto surfaceCapabilities2 = physicalDevices[i].getSurfaceCapabilities2KHR<vk::SurfaceCapabilities2KHR, vk::DisplayNativeHdrSurfaceCapabilitiesAMD, auto surfaceCapabilities2 =
vk::SharedPresentSurfaceCapabilitiesKHR, vk::SurfaceCapabilitiesFullScreenExclusiveEXT, physicalDevices[i]
vk::SurfaceProtectedCapabilitiesKHR>(*surfaceData.surface); .getSurfaceCapabilities2KHR<vk::SurfaceCapabilities2KHR,
vk::DisplayNativeHdrSurfaceCapabilitiesAMD,
vk::SharedPresentSurfaceCapabilitiesKHR,
vk::SurfaceCapabilitiesFullScreenExclusiveEXT,
vk::SurfaceProtectedCapabilitiesKHR>( *surfaceData.surface );
vk::SurfaceCapabilitiesKHR const& surfaceCapabilities = surfaceCapabilities2.get<vk::SurfaceCapabilities2KHR>().surfaceCapabilities; vk::SurfaceCapabilitiesKHR const & surfaceCapabilities =
cout(surfaceCapabilities); surfaceCapabilities2.get<vk::SurfaceCapabilities2KHR>().surfaceCapabilities;
cout( surfaceCapabilities );
if (vk::su::contains(extensionProperties, "VK_AMD_display_native_hdr")) if ( vk::su::contains( extensionProperties, "VK_AMD_display_native_hdr" ) )
{ {
vk::DisplayNativeHdrSurfaceCapabilitiesAMD displayNativeHdrSurfaceCapabilities = surfaceCapabilities2.get<vk::DisplayNativeHdrSurfaceCapabilitiesAMD>(); vk::DisplayNativeHdrSurfaceCapabilitiesAMD displayNativeHdrSurfaceCapabilities =
surfaceCapabilities2.get<vk::DisplayNativeHdrSurfaceCapabilitiesAMD>();
std::cout << "\tDisplayNativeHdrSurfaceCapabilitiesAMD:\n"; std::cout << "\tDisplayNativeHdrSurfaceCapabilitiesAMD:\n";
std::cout << "\t\t" << "localDimmingSupport = " << static_cast<bool>(displayNativeHdrSurfaceCapabilities.localDimmingSupport) << "\n"; std::cout << "\t\t"
<< "localDimmingSupport = "
<< static_cast<bool>( displayNativeHdrSurfaceCapabilities.localDimmingSupport ) << "\n";
std::cout << "\n"; std::cout << "\n";
} }
if (vk::su::contains(extensionProperties, "VK_KHR_shared_presentable_image")) if ( vk::su::contains( extensionProperties, "VK_KHR_shared_presentable_image" ) )
{ {
vk::SharedPresentSurfaceCapabilitiesKHR sharedPresentSurfaceCapabilities = surfaceCapabilities2.get<vk::SharedPresentSurfaceCapabilitiesKHR>(); vk::SharedPresentSurfaceCapabilitiesKHR sharedPresentSurfaceCapabilities =
surfaceCapabilities2.get<vk::SharedPresentSurfaceCapabilitiesKHR>();
std::cout << "\tSharedPresentSurfaceCapabilitiesKHR:\n"; std::cout << "\tSharedPresentSurfaceCapabilitiesKHR:\n";
std::cout << "\t\t" << "sharedPresentSupportedUsageFlags = " << vk::to_string(sharedPresentSurfaceCapabilities.sharedPresentSupportedUsageFlags) << "\n"; std::cout << "\t\t"
<< "sharedPresentSupportedUsageFlags = "
<< vk::to_string( sharedPresentSurfaceCapabilities.sharedPresentSupportedUsageFlags ) << "\n";
std::cout << "\n"; std::cout << "\n";
} }
if (vk::su::contains(extensionProperties, "VK_EXT_full_screen_exclusive")) if ( vk::su::contains( extensionProperties, "VK_EXT_full_screen_exclusive" ) )
{ {
vk::SurfaceCapabilitiesFullScreenExclusiveEXT surfaceCapabilitiesFullScreenExclusive = surfaceCapabilities2.get<vk::SurfaceCapabilitiesFullScreenExclusiveEXT>(); vk::SurfaceCapabilitiesFullScreenExclusiveEXT surfaceCapabilitiesFullScreenExclusive =
surfaceCapabilities2.get<vk::SurfaceCapabilitiesFullScreenExclusiveEXT>();
std::cout << "\tSurfaceCapabilitiesFullScreenExclusiveEXT:\n"; std::cout << "\tSurfaceCapabilitiesFullScreenExclusiveEXT:\n";
std::cout << "\t\t" << "fullScreenExclusiveSupported = " << static_cast<bool>(surfaceCapabilitiesFullScreenExclusive.fullScreenExclusiveSupported) << "\n"; std::cout << "\t\t"
<< "fullScreenExclusiveSupported = "
<< static_cast<bool>( surfaceCapabilitiesFullScreenExclusive.fullScreenExclusiveSupported ) << "\n";
std::cout << "\n"; std::cout << "\n";
} }
if (vk::su::contains(extensionProperties, "VK_KHR_surface_protected_capabilities")) if ( vk::su::contains( extensionProperties, "VK_KHR_surface_protected_capabilities" ) )
{ {
vk::SurfaceProtectedCapabilitiesKHR surfaceProtectedCapabilities = surfaceCapabilities2.get<vk::SurfaceProtectedCapabilitiesKHR>(); vk::SurfaceProtectedCapabilitiesKHR surfaceProtectedCapabilities =
surfaceCapabilities2.get<vk::SurfaceProtectedCapabilitiesKHR>();
std::cout << "\tSurfaceProtectedCapabilitiesKHR:\n"; std::cout << "\tSurfaceProtectedCapabilitiesKHR:\n";
std::cout << "\t\t" << "supportsProtected = " << static_cast<bool>(surfaceProtectedCapabilities.supportsProtected) << "\n"; std::cout << "\t\t"
<< "supportsProtected = " << static_cast<bool>( surfaceProtectedCapabilities.supportsProtected )
<< "\n";
std::cout << "\n"; std::cout << "\n";
} }
} }
else else
{ {
vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevices[i].getSurfaceCapabilitiesKHR(*surfaceData.surface); vk::SurfaceCapabilitiesKHR surfaceCapabilities =
cout(surfaceCapabilities); physicalDevices[i].getSurfaceCapabilitiesKHR( *surfaceData.surface );
cout( surfaceCapabilities );
} }
} }
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -17,59 +17,63 @@
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
static char const* AppName = "SurfaceFormats"; static char const * AppName = "SurfaceFormats";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
// enumerate the physicalDevices // enumerate the physicalDevices
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices(); std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
std::cout << std::boolalpha; std::cout << std::boolalpha;
for (size_t i=0 ; i<physicalDevices.size() ; i++) for ( size_t i = 0; i < physicalDevices.size(); i++ )
{ {
std::cout << "PhysicalDevice " << i << "\n"; std::cout << "PhysicalDevice " << i << "\n";
std::vector<vk::SurfaceFormatKHR> surfaceFormats = physicalDevices[i].getSurfaceFormatsKHR(*surfaceData.surface); std::vector<vk::SurfaceFormatKHR> surfaceFormats =
for (size_t j = 0; j < surfaceFormats.size(); j++) physicalDevices[i].getSurfaceFormatsKHR( *surfaceData.surface );
for ( size_t j = 0; j < surfaceFormats.size(); j++ )
{ {
std::cout << "\tFormat " << j << "\n"; std::cout << "\tFormat " << j << "\n";
std::cout << "\t\t" << "colorSpace = " << vk::to_string(surfaceFormats[j].colorSpace) << "\n"; std::cout << "\t\t"
std::cout << "\t\t" << "format = " << vk::to_string(surfaceFormats[j].format) << "\n"; << "colorSpace = " << vk::to_string( surfaceFormats[j].colorSpace ) << "\n";
std::cout << "\t\t"
<< "format = " << vk::to_string( surfaceFormats[j].format ) << "\n";
std::cout << "\n"; std::cout << "\n";
} }
} }
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,125 +19,181 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "Template"; static char const * AppName = "Template";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::DepthBufferData depthBufferData(physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent); vk::su::DepthBufferData depthBufferData( physicalDevice, device, vk::Format::eD16Unorm, surfaceData.extent );
vk::su::TextureData textureData(physicalDevice, device); vk::su::TextureData textureData( physicalDevice, device );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
textureData.setImage(device, commandBuffer, vk::su::CheckerboardImageGenerator()); textureData.setImage( device, commandBuffer, vk::su::CheckerboardImageGenerator() );
vk::su::BufferData uniformBufferData(physicalDevice, device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer); vk::su::BufferData uniformBufferData(
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix(surfaceData.extent)); physicalDevice, device, sizeof( glm::mat4x4 ), vk::BufferUsageFlagBits::eUniformBuffer );
vk::su::copyToDevice(
device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix( surfaceData.extent ) );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
{ {vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex}, {vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment} }); device,
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); { { vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex },
{ vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, depthBufferData.format); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
depthBufferData.format );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent );
vk::su::BufferData vertexBufferData(physicalDevice, device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer); vk::su::BufferData vertexBufferData(
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0])); physicalDevice, device, sizeof( texturedCubeData ), vk::BufferUsageFlagBits::eVertexBuffer );
vk::su::copyToDevice( device,
vertexBufferData.deviceMemory,
texturedCubeData,
sizeof( texturedCubeData ) / sizeof( texturedCubeData[0] ) );
vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, { {vk::DescriptorType::eUniformBuffer, 1}, {vk::DescriptorType::eCombinedImageSampler, 1} }); vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); device, { { vk::DescriptorType::eUniformBuffer, 1 }, { vk::DescriptorType::eCombinedImageSampler, 1 } } );
vk::su::updateDescriptorSets(device, descriptorSet, {{vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView()}}, textureData); vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::su::updateDescriptorSets(
device,
descriptorSet,
{ { vk::DescriptorType::eUniformBuffer, uniformBufferData.buffer, vk::UniqueBufferView() } },
textureData );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline =
sizeof(texturedCubeData[0]), {{ vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 }}, vk::su::createGraphicsPipeline( device,
vk::FrontFace::eClockwise, true, pipelineLayout, renderPass); pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
sizeof( texturedCubeData[0] ),
{ { vk::Format::eR32G32B32A32Sfloat, 0 }, { vk::Format::eR32G32Sfloat, 16 } },
vk::FrontFace::eClockwise,
true,
pipelineLayout,
renderPass );
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
vk::ClearValue clearValues[2]; vk::ClearValue clearValues[2];
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValues[0].color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0); clearValues[1].depthStencil = vk::ClearDepthStencilValue( 1.0f, 0 );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
framebuffers[currentBuffer.value].get(),
vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
2,
clearValues );
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr); commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr );
commandBuffer->bindVertexBuffers(0, *vertexBufferData.buffer, {0}); commandBuffer->bindVertexBuffers( 0, *vertexBufferData.buffer, { 0 } );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(12 * 3, 1, 0, 0); commandBuffer->draw( 12 * 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,13 +19,14 @@
#include "../utils/math.hpp" #include "../utils/math.hpp"
#include "../utils/shaders.hpp" #include "../utils/shaders.hpp"
#include "../utils/utils.hpp" #include "../utils/utils.hpp"
#include "vulkan/vulkan.hpp"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
static char const* AppName = "TexelBuffer"; static char const * AppName = "TexelBuffer";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
static const std::string vertexShaderText = R"( static const std::string vertexShaderText = R"(
#version 400 #version 400
@ -52,128 +53,179 @@ void main()
} }
)"; )";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
const float texels[] = {118.0f / 255.0f, 185.0f / 255.0f, 0.0f}; const float texels[] = { 118.0f / 255.0f, 185.0f / 255.0f, 0.0f };
try try
{ {
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, {}, vk::su::getInstanceExtensions()); vk::UniqueInstance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
#if !defined(NDEBUG) #if !defined( NDEBUG )
vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger(instance); vk::UniqueDebugUtilsMessengerEXT debugUtilsMessenger = vk::su::createDebugUtilsMessenger( instance );
#endif #endif
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
vk::PhysicalDeviceProperties physicalDeviceProperties = physicalDevice.getProperties(); vk::PhysicalDeviceProperties physicalDeviceProperties = physicalDevice.getProperties();
if (physicalDeviceProperties.limits.maxTexelBufferElements < 4) if ( physicalDeviceProperties.limits.maxTexelBufferElements < 4 )
{ {
std::cout << "maxTexelBufferElements too small\n"; std::cout << "maxTexelBufferElements too small\n";
exit(-1); exit( -1 );
} }
vk::Format texelFormat = vk::Format::eR32Sfloat; vk::Format texelFormat = vk::Format::eR32Sfloat;
vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(texelFormat); vk::FormatProperties formatProperties = physicalDevice.getFormatProperties( texelFormat );
if (!(formatProperties.bufferFeatures & vk::FormatFeatureFlagBits::eUniformTexelBuffer)) if ( !( formatProperties.bufferFeatures & vk::FormatFeatureFlagBits::eUniformTexelBuffer ) )
{ {
std::cout << "R32_SFLOAT format unsupported for texel buffer\n"; std::cout << "R32_SFLOAT format unsupported for texel buffer\n";
exit(-1); exit( -1 );
} }
vk::su::SurfaceData surfaceData(instance, AppName, vk::Extent2D(500, 500)); vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 500, 500 ) );
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevice, *surfaceData.surface); std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex =
vk::UniqueDevice device = vk::su::createDevice(physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions()); vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, *surfaceData.surface );
vk::UniqueDevice device =
vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first); vk::UniqueCommandPool commandPool = vk::su::createCommandPool( device, graphicsAndPresentQueueFamilyIndex.first );
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0); vk::Queue graphicsQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0); vk::Queue presentQueue = device->getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
vk::su::SwapChainData swapChainData(physicalDevice, device, *surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc, vk::su::SwapChainData swapChainData( physicalDevice,
vk::UniqueSwapchainKHR(), graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second); device,
*surfaceData.surface,
surfaceData.extent,
vk::ImageUsageFlagBits::eColorAttachment |
vk::ImageUsageFlagBits::eTransferSrc,
vk::UniqueSwapchainKHR(),
graphicsAndPresentQueueFamilyIndex.first,
graphicsAndPresentQueueFamilyIndex.second );
vk::su::BufferData texelBufferData(physicalDevice, device, sizeof(texels), vk::BufferUsageFlagBits::eUniformTexelBuffer); vk::su::BufferData texelBufferData(
texelBufferData.upload(device, texels); physicalDevice, device, sizeof( texels ), vk::BufferUsageFlagBits::eUniformTexelBuffer );
texelBufferData.upload( device, texels );
vk::UniqueBufferView texelBufferView = device->createBufferViewUnique(vk::BufferViewCreateInfo({}, *texelBufferData.buffer, texelFormat, 0, sizeof(texels))); vk::UniqueBufferView texelBufferView = device->createBufferViewUnique(
vk::BufferViewCreateInfo( {}, *texelBufferData.buffer, texelFormat, 0, sizeof( texels ) ) );
vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(device, { {vk::DescriptorType::eUniformTexelBuffer, 1, vk::ShaderStageFlagBits::eVertex} }); vk::UniqueDescriptorSetLayout descriptorSetLayout = vk::su::createDescriptorSetLayout(
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get())); device, { { vk::DescriptorType::eUniformTexelBuffer, 1, vk::ShaderStageFlagBits::eVertex } } );
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(
vk::PipelineLayoutCreateInfo( vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get() ) );
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickSurfaceFormat(physicalDevice.getSurfaceFormatsKHR(surfaceData.surface.get())).format, vk::Format::eUndefined); vk::UniqueRenderPass renderPass = vk::su::createRenderPass(
device,
vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surfaceData.surface.get() ) ).format,
vk::Format::eUndefined );
glslang::InitializeProcess(); glslang::InitializeProcess();
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText); vk::UniqueShaderModule vertexShaderModule =
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C); vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eVertex, vertexShaderText );
vk::UniqueShaderModule fragmentShaderModule =
vk::su::createShaderModule( device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_C_C );
glslang::FinalizeProcess(); glslang::FinalizeProcess();
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, vk::UniqueImageView(), surfaceData.extent); std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(
device, renderPass, swapChainData.imageViews, vk::UniqueImageView(), surfaceData.extent );
vk::UniqueDescriptorPool descriptorPool = vk::su::createDescriptorPool(device, { {vk::DescriptorType::eUniformTexelBuffer, 1} }); vk::UniqueDescriptorPool descriptorPool =
vk::UniqueDescriptorSet descriptorSet = std::move(device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(*descriptorPool, 1, &*descriptorSetLayout)).front()); vk::su::createDescriptorPool( device, { { vk::DescriptorType::eUniformTexelBuffer, 1 } } );
vk::su::updateDescriptorSets(device, descriptorSet, {{vk::DescriptorType::eUniformTexelBuffer, texelBufferData.buffer, texelBufferView}}, {}); vk::UniqueDescriptorSet descriptorSet = std::move(
device->allocateDescriptorSetsUnique( vk::DescriptorSetAllocateInfo( *descriptorPool, 1, &*descriptorSetLayout ) )
.front() );
vk::su::updateDescriptorSets(
device,
descriptorSet,
{ { vk::DescriptorType::eUniformTexelBuffer, texelBufferData.buffer, texelBufferView } },
{} );
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo()); vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique( vk::PipelineCacheCreateInfo() );
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, std::make_pair(*vertexShaderModule, nullptr), std::make_pair(*fragmentShaderModule, nullptr), vk::UniquePipeline graphicsPipeline =
0, {}, vk::FrontFace::eClockwise, false, pipelineLayout, renderPass); vk::su::createGraphicsPipeline( device,
pipelineCache,
std::make_pair( *vertexShaderModule, nullptr ),
std::make_pair( *fragmentShaderModule, nullptr ),
0,
{},
vk::FrontFace::eClockwise,
false,
pipelineLayout,
renderPass );
/* VULKAN_KEY_START */ /* VULKAN_KEY_START */
// Get the index of the next available swapchain image: // Get the index of the next available swapchain image:
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo()); vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique( vk::SemaphoreCreateInfo() );
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr); vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(
assert(currentBuffer.result == vk::Result::eSuccess); swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr );
assert(currentBuffer.value < framebuffers.size()); assert( currentBuffer.result == vk::Result::eSuccess );
assert( currentBuffer.value < framebuffers.size() );
commandBuffer->begin(vk::CommandBufferBeginInfo()); commandBuffer->begin( vk::CommandBufferBeginInfo() );
vk::ClearValue clearValue; vk::ClearValue clearValue;
clearValue.color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f })); clearValue.color = vk::ClearColorValue( std::array<float, 4>( { 0.2f, 0.2f, 0.2f, 0.2f } ) );
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 1, &clearValue); vk::RenderPassBeginInfo renderPassBeginInfo( renderPass.get(),
framebuffers[currentBuffer.value].get(),
vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ),
1,
&clearValue );
commandBuffer->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline); commandBuffer->beginRenderPass( renderPassBeginInfo, vk::SubpassContents::eInline );
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get()); commandBuffer->bindPipeline( vk::PipelineBindPoint::eGraphics, graphicsPipeline.get() );
commandBuffer->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr); commandBuffer->bindDescriptorSets(
vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSet.get(), nullptr );
commandBuffer->setViewport(0, vk::Viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f)); commandBuffer->setViewport( 0,
commandBuffer->setScissor(0, vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent)); vk::Viewport( 0.0f,
0.0f,
static_cast<float>( surfaceData.extent.width ),
static_cast<float>( surfaceData.extent.height ),
0.0f,
1.0f ) );
commandBuffer->setScissor( 0, vk::Rect2D( vk::Offset2D( 0, 0 ), surfaceData.extent ) );
commandBuffer->draw(3, 1, 0, 0); commandBuffer->draw( 3, 1, 0, 0 );
commandBuffer->endRenderPass(); commandBuffer->endRenderPass();
commandBuffer->end(); commandBuffer->end();
vk::UniqueFence drawFence = device->createFenceUnique(vk::FenceCreateInfo()); vk::UniqueFence drawFence = device->createFenceUnique( vk::FenceCreateInfo() );
vk::PipelineStageFlags waitDestinationStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput); vk::PipelineStageFlags waitDestinationStageMask( vk::PipelineStageFlagBits::eColorAttachmentOutput );
vk::SubmitInfo submitInfo(1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get()); vk::SubmitInfo submitInfo( 1, &imageAcquiredSemaphore.get(), &waitDestinationStageMask, 1, &commandBuffer.get() );
graphicsQueue.submit(submitInfo, drawFence.get()); graphicsQueue.submit( submitInfo, drawFence.get() );
while (vk::Result::eTimeout == device->waitForFences(drawFence.get(), VK_TRUE, vk::su::FenceTimeout)) while ( vk::Result::eTimeout == device->waitForFences( drawFence.get(), VK_TRUE, vk::su::FenceTimeout ) )
; ;
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value)); presentQueue.presentKHR(
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); vk::PresentInfoKHR( 0, nullptr, 1, &swapChainData.swapChain.get(), &currentBuffer.value ) );
std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
/* VULKAN_KEY_END */ /* VULKAN_KEY_END */
device->waitIdle(); device->waitIdle();
} }
catch (vk::SystemError& err) catch ( vk::SystemError & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (std::runtime_error& err) catch ( std::runtime_error & err )
{ {
std::cout << "std::runtime_error: " << err.what() << std::endl; std::cout << "std::runtime_error: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -19,19 +19,35 @@ namespace vk
{ {
namespace su namespace su
{ {
glm::mat4x4 createModelViewProjectionClipMatrix(vk::Extent2D const& extent) glm::mat4x4 createModelViewProjectionClipMatrix( vk::Extent2D const & extent )
{ {
float fov = glm::radians(45.0f); float fov = glm::radians( 45.0f );
if (extent.width > extent.height) if ( extent.width > extent.height )
{ {
fov *= static_cast<float>(extent.height) / static_cast<float>(extent.width); fov *= static_cast<float>( extent.height ) / static_cast<float>( extent.width );
} }
glm::mat4x4 model = glm::mat4x4(1.0f); glm::mat4x4 model = glm::mat4x4( 1.0f );
glm::mat4x4 view = glm::lookAt(glm::vec3(-5.0f, 3.0f, -10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)); glm::mat4x4 view =
glm::mat4x4 projection = glm::perspective(fov, 1.0f, 0.1f, 100.0f); glm::lookAt( glm::vec3( -5.0f, 3.0f, -10.0f ), glm::vec3( 0.0f, 0.0f, 0.0f ), glm::vec3( 0.0f, -1.0f, 0.0f ) );
glm::mat4x4 clip = glm::mat4x4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f); // vulkan clip space has inverted y and half z ! glm::mat4x4 projection = glm::perspective( fov, 1.0f, 0.1f, 100.0f );
glm::mat4x4 clip = glm::mat4x4( 1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
-1.0f,
0.0f,
0.0f,
0.0f,
0.0f,
0.5f,
0.0f,
0.0f,
0.0f,
0.5f,
1.0f ); // vulkan clip space has inverted y and half z !
return clip * projection * view * model; return clip * projection * view * model;
} }
} } // namespace su
} } // namespace vk

View File

@ -15,13 +15,14 @@
#include <vulkan/vulkan.hpp> #include <vulkan/vulkan.hpp>
#define GLM_FORCE_RADIANS #define GLM_FORCE_RADIANS
#pragma warning(disable:4201) // disable warning C4201: nonstandard extension used: nameless struct/union; needed to get glm/detail/type_vec?.hpp without warnings #pragma warning( disable : 4201 ) // disable warning C4201: nonstandard extension used: nameless struct/union; needed
// to get glm/detail/type_vec?.hpp without warnings
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
namespace vk namespace vk
{ {
namespace su namespace su
{ {
glm::mat4x4 createModelViewProjectionClipMatrix(vk::Extent2D const& extent); glm::mat4x4 createModelViewProjectionClipMatrix( vk::Extent2D const & extent );
} }
} } // namespace vk

View File

@ -14,85 +14,88 @@
// //
#include "shaders.hpp" #include "shaders.hpp"
#include "vulkan/vulkan.hpp"
#include "StandAlone/ResourceLimits.h"
#include "SPIRV/GlslangToSpv.h" #include "SPIRV/GlslangToSpv.h"
#include "StandAlone/ResourceLimits.h"
#include "vulkan/vulkan.hpp"
namespace vk namespace vk
{ {
namespace su namespace su
{ {
EShLanguage translateShaderStage( vk::ShaderStageFlagBits stage )
EShLanguage translateShaderStage(vk::ShaderStageFlagBits stage)
{ {
switch (stage) switch ( stage )
{ {
case vk::ShaderStageFlagBits::eVertex: return EShLangVertex; case vk::ShaderStageFlagBits::eVertex: return EShLangVertex;
case vk::ShaderStageFlagBits::eTessellationControl: return EShLangTessControl; case vk::ShaderStageFlagBits::eTessellationControl: return EShLangTessControl;
case vk::ShaderStageFlagBits::eTessellationEvaluation: return EShLangTessEvaluation; case vk::ShaderStageFlagBits::eTessellationEvaluation: return EShLangTessEvaluation;
case vk::ShaderStageFlagBits::eGeometry: return EShLangGeometry; case vk::ShaderStageFlagBits::eGeometry: return EShLangGeometry;
case vk::ShaderStageFlagBits::eFragment: return EShLangFragment; case vk::ShaderStageFlagBits::eFragment: return EShLangFragment;
case vk::ShaderStageFlagBits::eCompute: return EShLangCompute; case vk::ShaderStageFlagBits::eCompute: return EShLangCompute;
case vk::ShaderStageFlagBits::eRaygenNV: return EShLangRayGenNV; case vk::ShaderStageFlagBits::eRaygenNV: return EShLangRayGenNV;
case vk::ShaderStageFlagBits::eAnyHitNV: return EShLangAnyHitNV; case vk::ShaderStageFlagBits::eAnyHitNV: return EShLangAnyHitNV;
case vk::ShaderStageFlagBits::eClosestHitNV: return EShLangClosestHitNV; case vk::ShaderStageFlagBits::eClosestHitNV: return EShLangClosestHitNV;
case vk::ShaderStageFlagBits::eMissNV: return EShLangMissNV; case vk::ShaderStageFlagBits::eMissNV: return EShLangMissNV;
case vk::ShaderStageFlagBits::eIntersectionNV: return EShLangIntersectNV; case vk::ShaderStageFlagBits::eIntersectionNV: return EShLangIntersectNV;
case vk::ShaderStageFlagBits::eCallableNV: return EShLangCallableNV; case vk::ShaderStageFlagBits::eCallableNV: return EShLangCallableNV;
case vk::ShaderStageFlagBits::eTaskNV: return EShLangTaskNV; case vk::ShaderStageFlagBits::eTaskNV: return EShLangTaskNV;
case vk::ShaderStageFlagBits::eMeshNV: return EShLangMeshNV; case vk::ShaderStageFlagBits::eMeshNV: return EShLangMeshNV;
default: default: assert( false && "Unknown shader stage" ); return EShLangVertex;
assert(false && "Unknown shader stage");
return EShLangVertex;
} }
} }
bool GLSLtoSPV(const vk::ShaderStageFlagBits shaderType, std::string const& glslShader, std::vector<unsigned int> &spvShader) bool GLSLtoSPV( const vk::ShaderStageFlagBits shaderType,
std::string const & glslShader,
std::vector<unsigned int> & spvShader )
{ {
EShLanguage stage = translateShaderStage(shaderType); EShLanguage stage = translateShaderStage( shaderType );
const char *shaderStrings[1]; const char * shaderStrings[1];
shaderStrings[0] = glslShader.data(); shaderStrings[0] = glslShader.data();
glslang::TShader shader(stage); glslang::TShader shader( stage );
shader.setStrings(shaderStrings, 1); shader.setStrings( shaderStrings, 1 );
// Enable SPIR-V and Vulkan rules when parsing GLSL // Enable SPIR-V and Vulkan rules when parsing GLSL
EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); EShMessages messages = ( EShMessages )( EShMsgSpvRules | EShMsgVulkanRules );
if (!shader.parse(&glslang::DefaultTBuiltInResource, 100, false, messages)) if ( !shader.parse( &glslang::DefaultTBuiltInResource, 100, false, messages ) )
{ {
puts(shader.getInfoLog()); puts( shader.getInfoLog() );
puts(shader.getInfoDebugLog()); puts( shader.getInfoDebugLog() );
return false; // something didn't work return false; // something didn't work
} }
glslang::TProgram program; glslang::TProgram program;
program.addShader(&shader); program.addShader( &shader );
// //
// Program-level processing... // Program-level processing...
// //
if (!program.link(messages)) if ( !program.link( messages ) )
{ {
puts(shader.getInfoLog()); puts( shader.getInfoLog() );
puts(shader.getInfoDebugLog()); puts( shader.getInfoDebugLog() );
fflush(stdout); fflush( stdout );
return false; return false;
} }
glslang::GlslangToSpv(*program.getIntermediate(stage), spvShader); glslang::GlslangToSpv( *program.getIntermediate( stage ), spvShader );
return true; return true;
} }
vk::UniqueShaderModule createShaderModule(vk::UniqueDevice &device, vk::ShaderStageFlagBits shaderStage, std::string const& shaderText) vk::UniqueShaderModule createShaderModule( vk::UniqueDevice & device,
vk::ShaderStageFlagBits shaderStage,
std::string const & shaderText )
{ {
std::vector<unsigned int> shaderSPV; std::vector<unsigned int> shaderSPV;
bool ok = GLSLtoSPV(shaderStage, shaderText, shaderSPV); bool ok = GLSLtoSPV( shaderStage, shaderText, shaderSPV );
assert(ok); assert( ok );
return device->createShaderModuleUnique(vk::ShaderModuleCreateInfo(vk::ShaderModuleCreateFlags(), shaderSPV.size() * sizeof(unsigned int), shaderSPV.data())); return device->createShaderModuleUnique( vk::ShaderModuleCreateInfo(
vk::ShaderModuleCreateFlags(), shaderSPV.size() * sizeof( unsigned int ), shaderSPV.data() ) );
} }
} } // namespace su
} } // namespace vk

View File

@ -14,6 +14,7 @@
// //
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
@ -21,12 +22,15 @@ namespace vk
{ {
namespace su namespace su
{ {
vk::UniqueShaderModule createShaderModule(vk::UniqueDevice &device, vk::ShaderStageFlagBits shaderStage, std::string const& shaderText); vk::UniqueShaderModule createShaderModule( vk::UniqueDevice & device,
vk::ShaderStageFlagBits shaderStage,
bool GLSLtoSPV(const vk::ShaderStageFlagBits shaderType, std::string const& glslShader, std::vector<unsigned int> &spvShader); std::string const & shaderText );
}
}
bool GLSLtoSPV( const vk::ShaderStageFlagBits shaderType,
std::string const & glslShader,
std::vector<unsigned int> & spvShader );
} // namespace su
} // namespace vk
// vertex shader with (P)osition and (C)olor in and (C)olor out // vertex shader with (P)osition and (C)olor in and (C)olor out
const std::string vertexShaderText_PC_C = R"( const std::string vertexShaderText_PC_C = R"(
@ -76,7 +80,6 @@ void main()
} }
)"; )";
// fragment shader with (C)olor in and (C)olor out // fragment shader with (C)olor in and (C)olor out
const std::string fragmentShaderText_C_C = R"( const std::string fragmentShaderText_C_C = R"(
#version 400 #version 400
@ -112,4 +115,3 @@ void main()
outColor = texture(tex, inTexCoord); outColor = texture(tex, inTexCoord);
} }
)"; )";

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,6 @@
#define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <iostream> #include <iostream>
#include <map> #include <map>
@ -30,121 +29,146 @@ namespace vk
const uint64_t FenceTimeout = 100000000; const uint64_t FenceTimeout = 100000000;
template <typename Func> template <typename Func>
void oneTimeSubmit(vk::UniqueCommandBuffer const& commandBuffer, vk::Queue const& queue, Func const& func) void oneTimeSubmit( vk::UniqueCommandBuffer const & commandBuffer, vk::Queue const & queue, Func const & func )
{ {
commandBuffer->begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit)); commandBuffer->begin( vk::CommandBufferBeginInfo( vk::CommandBufferUsageFlagBits::eOneTimeSubmit ) );
func(commandBuffer); func( commandBuffer );
commandBuffer->end(); commandBuffer->end();
queue.submit(vk::SubmitInfo(0, nullptr, nullptr, 1, &(*commandBuffer)), nullptr); queue.submit( vk::SubmitInfo( 0, nullptr, nullptr, 1, &( *commandBuffer ) ), nullptr );
queue.waitIdle(); queue.waitIdle();
} }
template <typename Func> template <typename Func>
void oneTimeSubmit(vk::UniqueDevice const& device, vk::UniqueCommandPool const& commandPool, vk::Queue const& queue, Func const& func) void oneTimeSubmit( vk::UniqueDevice const & device,
vk::UniqueCommandPool const & commandPool,
vk::Queue const & queue,
Func const & func )
{ {
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(*commandPool, vk::CommandBufferLevel::ePrimary, 1)).front()); vk::UniqueCommandBuffer commandBuffer =
oneTimeSubmit(commandBuffer, queue, func); std::move( device
->allocateCommandBuffersUnique(
vk::CommandBufferAllocateInfo( *commandPool, vk::CommandBufferLevel::ePrimary, 1 ) )
.front() );
oneTimeSubmit( commandBuffer, queue, func );
} }
template <class T> template <class T>
void copyToDevice(vk::UniqueDevice const& device, vk::UniqueDeviceMemory const& memory, T const* pData, size_t count, vk::DeviceSize stride = sizeof(T)) void copyToDevice( vk::UniqueDevice const & device,
vk::UniqueDeviceMemory const & memory,
T const * pData,
size_t count,
vk::DeviceSize stride = sizeof( T ) )
{ {
assert(sizeof(T) <= stride); assert( sizeof( T ) <= stride );
uint8_t* deviceData = static_cast<uint8_t*>(device->mapMemory(memory.get(), 0, count * stride)); uint8_t * deviceData = static_cast<uint8_t *>( device->mapMemory( memory.get(), 0, count * stride ) );
if (stride == sizeof(T)) if ( stride == sizeof( T ) )
{ {
memcpy(deviceData, pData, count * sizeof(T)); memcpy( deviceData, pData, count * sizeof( T ) );
} }
else else
{ {
for (size_t i = 0; i < count; i++) for ( size_t i = 0; i < count; i++ )
{ {
memcpy(deviceData, &pData[i], sizeof(T)); memcpy( deviceData, &pData[i], sizeof( T ) );
deviceData += stride; deviceData += stride;
} }
} }
device->unmapMemory(memory.get()); device->unmapMemory( memory.get() );
} }
template <class T> template <class T>
void copyToDevice(vk::UniqueDevice const& device, vk::UniqueDeviceMemory const& memory, T const& data) void copyToDevice( vk::UniqueDevice const & device, vk::UniqueDeviceMemory const & memory, T const & data )
{ {
copyToDevice<T>(device, memory, &data, 1); copyToDevice<T>( device, memory, &data, 1 );
} }
template<class T> template <class T>
VULKAN_HPP_INLINE constexpr const T& clamp(const T& v, const T& lo, const T& hi) VULKAN_HPP_INLINE constexpr const T & clamp( const T & v, const T & lo, const T & hi )
{ {
return v < lo ? lo : hi < v ? hi : v; return v < lo ? lo : hi < v ? hi : v;
} }
void setImageLayout(vk::UniqueCommandBuffer const &commandBuffer, vk::Image image, vk::Format format, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout); void setImageLayout( vk::UniqueCommandBuffer const & commandBuffer,
vk::Image image,
vk::Format format,
vk::ImageLayout oldImageLayout,
vk::ImageLayout newImageLayout );
struct WindowData struct WindowData
{ {
WindowData(GLFWwindow *wnd, std::string const& name, vk::Extent2D const& extent); WindowData( GLFWwindow * wnd, std::string const & name, vk::Extent2D const & extent );
WindowData(const WindowData &) = delete; WindowData( const WindowData & ) = delete;
WindowData(WindowData &&other); WindowData( WindowData && other );
~WindowData() noexcept; ~WindowData() noexcept;
GLFWwindow *handle; GLFWwindow * handle;
std::string name; std::string name;
vk::Extent2D extent; vk::Extent2D extent;
}; };
WindowData createWindow(std::string const &windowName, vk::Extent2D const &extent); WindowData createWindow( std::string const & windowName, vk::Extent2D const & extent );
struct BufferData struct BufferData
{ {
BufferData(vk::PhysicalDevice const& physicalDevice, vk::UniqueDevice const& device, vk::DeviceSize size, vk::BufferUsageFlags usage, BufferData( vk::PhysicalDevice const & physicalDevice,
vk::MemoryPropertyFlags propertyFlags = vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent); vk::UniqueDevice const & device,
vk::DeviceSize size,
vk::BufferUsageFlags usage,
vk::MemoryPropertyFlags propertyFlags = vk::MemoryPropertyFlagBits::eHostVisible |
vk::MemoryPropertyFlagBits::eHostCoherent );
template <typename DataType> template <typename DataType>
void upload(vk::UniqueDevice const& device, DataType const& data) const void upload( vk::UniqueDevice const & device, DataType const & data ) const
{ {
assert((m_propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent) && (m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible)); assert( ( m_propertyFlags & vk::MemoryPropertyFlagBits::eHostCoherent ) &&
assert(sizeof(DataType) <= m_size); ( m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible ) );
assert( sizeof( DataType ) <= m_size );
void* dataPtr = device->mapMemory(*this->deviceMemory, 0, sizeof(DataType)); void * dataPtr = device->mapMemory( *this->deviceMemory, 0, sizeof( DataType ) );
memcpy(dataPtr, &data, sizeof(DataType)); memcpy( dataPtr, &data, sizeof( DataType ) );
device->unmapMemory(*this->deviceMemory); device->unmapMemory( *this->deviceMemory );
} }
template <typename DataType> template <typename DataType>
void upload(vk::UniqueDevice const& device, std::vector<DataType> const& data, size_t stride = 0) const void upload( vk::UniqueDevice const & device, std::vector<DataType> const & data, size_t stride = 0 ) const
{ {
assert(m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible); assert( m_propertyFlags & vk::MemoryPropertyFlagBits::eHostVisible );
size_t elementSize = stride ? stride : sizeof(DataType); size_t elementSize = stride ? stride : sizeof( DataType );
assert(sizeof(DataType) <= elementSize); assert( sizeof( DataType ) <= elementSize );
copyToDevice(device, deviceMemory, data.data(), data.size(), elementSize); copyToDevice( device, deviceMemory, data.data(), data.size(), elementSize );
} }
template <typename DataType> template <typename DataType>
void upload(vk::PhysicalDevice const& physicalDevice, vk::UniqueDevice const& device, vk::UniqueCommandPool const& commandPool, vk::Queue queue, std::vector<DataType> const& data, void upload( vk::PhysicalDevice const & physicalDevice,
size_t stride) const vk::UniqueDevice const & device,
vk::UniqueCommandPool const & commandPool,
vk::Queue queue,
std::vector<DataType> const & data,
size_t stride ) const
{ {
assert(m_usage & vk::BufferUsageFlagBits::eTransferDst); assert( m_usage & vk::BufferUsageFlagBits::eTransferDst );
assert(m_propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal); assert( m_propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal );
size_t elementSize = stride ? stride : sizeof(DataType); size_t elementSize = stride ? stride : sizeof( DataType );
assert(sizeof(DataType) <= elementSize); assert( sizeof( DataType ) <= elementSize );
size_t dataSize = data.size() * elementSize; size_t dataSize = data.size() * elementSize;
assert(dataSize <= m_size); assert( dataSize <= m_size );
vk::su::BufferData stagingBuffer(physicalDevice, device, dataSize, vk::BufferUsageFlagBits::eTransferSrc); vk::su::BufferData stagingBuffer( physicalDevice, device, dataSize, vk::BufferUsageFlagBits::eTransferSrc );
copyToDevice(device, stagingBuffer.deviceMemory, data.data(), data.size(), elementSize); copyToDevice( device, stagingBuffer.deviceMemory, data.data(), data.size(), elementSize );
vk::su::oneTimeSubmit(device, commandPool, queue, vk::su::oneTimeSubmit( device, commandPool, queue, [&]( vk::UniqueCommandBuffer const & commandBuffer ) {
[&](vk::UniqueCommandBuffer const& commandBuffer) { commandBuffer->copyBuffer(*stagingBuffer.buffer, *this->buffer, vk::BufferCopy(0, 0, dataSize)); }); commandBuffer->copyBuffer( *stagingBuffer.buffer, *this->buffer, vk::BufferCopy( 0, 0, dataSize ) );
} );
} }
vk::UniqueBuffer buffer; vk::UniqueBuffer buffer;
vk::UniqueDeviceMemory deviceMemory; vk::UniqueDeviceMemory deviceMemory;
#if !defined(NDEBUG) #if !defined( NDEBUG )
private: private:
vk::DeviceSize m_size; vk::DeviceSize m_size;
vk::BufferUsageFlags m_usage; vk::BufferUsageFlags m_usage;
vk::MemoryPropertyFlags m_propertyFlags; vk::MemoryPropertyFlags m_propertyFlags;
@ -153,104 +177,149 @@ namespace vk
struct ImageData struct ImageData
{ {
ImageData(vk::PhysicalDevice const& physicalDevice, vk::UniqueDevice const& device, vk::Format format, vk::Extent2D const& extent, vk::ImageTiling tiling, vk::ImageUsageFlags usage ImageData( vk::PhysicalDevice const & physicalDevice,
, vk::ImageLayout initialLayout, vk::MemoryPropertyFlags memoryProperties, vk::ImageAspectFlags aspectMask); vk::UniqueDevice const & device,
vk::Format format,
vk::Extent2D const & extent,
vk::ImageTiling tiling,
vk::ImageUsageFlags usage,
vk::ImageLayout initialLayout,
vk::MemoryPropertyFlags memoryProperties,
vk::ImageAspectFlags aspectMask );
vk::Format format; vk::Format format;
vk::UniqueImage image; vk::UniqueImage image;
vk::UniqueDeviceMemory deviceMemory; vk::UniqueDeviceMemory deviceMemory;
vk::UniqueImageView imageView; vk::UniqueImageView imageView;
}; };
struct DepthBufferData : public ImageData struct DepthBufferData : public ImageData
{ {
DepthBufferData(vk::PhysicalDevice &physicalDevice, vk::UniqueDevice & device, vk::Format format, vk::Extent2D const& extent); DepthBufferData( vk::PhysicalDevice & physicalDevice,
vk::UniqueDevice & device,
vk::Format format,
vk::Extent2D const & extent );
}; };
struct SurfaceData struct SurfaceData
{ {
SurfaceData(vk::UniqueInstance &instance, std::string const& windowName, vk::Extent2D const& extent); SurfaceData( vk::UniqueInstance & instance, std::string const & windowName, vk::Extent2D const & extent );
vk::Extent2D extent; vk::Extent2D extent;
WindowData window; WindowData window;
vk::UniqueSurfaceKHR surface; vk::UniqueSurfaceKHR surface;
}; };
struct SwapChainData struct SwapChainData
{ {
SwapChainData(vk::PhysicalDevice const& physicalDevice, vk::UniqueDevice const& device, vk::SurfaceKHR const& surface, vk::Extent2D const& extent, vk::ImageUsageFlags usage, SwapChainData( vk::PhysicalDevice const & physicalDevice,
vk::UniqueSwapchainKHR const& oldSwapChain, uint32_t graphicsFamilyIndex, uint32_t presentFamilyIndex); vk::UniqueDevice const & device,
vk::SurfaceKHR const & surface,
vk::Extent2D const & extent,
vk::ImageUsageFlags usage,
vk::UniqueSwapchainKHR const & oldSwapChain,
uint32_t graphicsFamilyIndex,
uint32_t presentFamilyIndex );
vk::Format colorFormat; vk::Format colorFormat;
vk::UniqueSwapchainKHR swapChain; vk::UniqueSwapchainKHR swapChain;
std::vector<vk::Image> images; std::vector<vk::Image> images;
std::vector<vk::UniqueImageView> imageViews; std::vector<vk::UniqueImageView> imageViews;
}; };
class CheckerboardImageGenerator class CheckerboardImageGenerator
{ {
public: public:
CheckerboardImageGenerator(std::array<uint8_t, 3> const& rgb0 = {0, 0, 0}, std::array<uint8_t, 3> const& rgb1 = {255, 255, 255}); CheckerboardImageGenerator( std::array<uint8_t, 3> const & rgb0 = { 0, 0, 0 },
std::array<uint8_t, 3> const & rgb1 = { 255, 255, 255 } );
void operator()(void* data, vk::Extent2D &extent) const; void operator()( void * data, vk::Extent2D & extent ) const;
private: private:
std::array<uint8_t, 3> const& m_rgb0; std::array<uint8_t, 3> const & m_rgb0;
std::array<uint8_t, 3> const& m_rgb1; std::array<uint8_t, 3> const & m_rgb1;
}; };
class MonochromeImageGenerator class MonochromeImageGenerator
{ {
public: public:
MonochromeImageGenerator(std::array<unsigned char, 3> const& rgb); MonochromeImageGenerator( std::array<unsigned char, 3> const & rgb );
void operator()(void* data, vk::Extent2D &extent) const; void operator()( void * data, vk::Extent2D & extent ) const;
private: private:
std::array<unsigned char, 3> const& m_rgb; std::array<unsigned char, 3> const & m_rgb;
}; };
class PixelsImageGenerator class PixelsImageGenerator
{ {
public: public:
PixelsImageGenerator(vk::Extent2D const& extent, size_t channels, unsigned char const* pixels); PixelsImageGenerator( vk::Extent2D const & extent, size_t channels, unsigned char const * pixels );
void operator()(void* data, vk::Extent2D & extent) const; void operator()( void * data, vk::Extent2D & extent ) const;
private: private:
vk::Extent2D m_extent; vk::Extent2D m_extent;
size_t m_channels; size_t m_channels;
unsigned char const* m_pixels; unsigned char const * m_pixels;
}; };
struct TextureData struct TextureData
{ {
TextureData(vk::PhysicalDevice const& physicalDevice, vk::UniqueDevice const& device, vk::Extent2D const& extent_ = {256, 256}, vk::ImageUsageFlags usageFlags = {}, TextureData( vk::PhysicalDevice const & physicalDevice,
vk::FormatFeatureFlags formatFeatureFlags = {}, bool anisotropyEnable = false, bool forceStaging = false); vk::UniqueDevice const & device,
vk::Extent2D const & extent_ = { 256, 256 },
vk::ImageUsageFlags usageFlags = {},
vk::FormatFeatureFlags formatFeatureFlags = {},
bool anisotropyEnable = false,
bool forceStaging = false );
template <typename ImageGenerator> template <typename ImageGenerator>
void setImage(vk::UniqueDevice const& device, vk::UniqueCommandBuffer const& commandBuffer, ImageGenerator const& imageGenerator) void setImage( vk::UniqueDevice const & device,
vk::UniqueCommandBuffer const & commandBuffer,
ImageGenerator const & imageGenerator )
{ {
void* data = needsStaging void * data =
? device->mapMemory(stagingBufferData->deviceMemory.get(), 0, device->getBufferMemoryRequirements(stagingBufferData->buffer.get()).size) needsStaging
: device->mapMemory(imageData->deviceMemory.get(), 0, device->getImageMemoryRequirements(imageData->image.get()).size); ? device->mapMemory( stagingBufferData->deviceMemory.get(),
imageGenerator(data, extent); 0,
device->unmapMemory(needsStaging ? stagingBufferData->deviceMemory.get() : imageData->deviceMemory.get()); device->getBufferMemoryRequirements( stagingBufferData->buffer.get() ).size )
: device->mapMemory(
imageData->deviceMemory.get(), 0, device->getImageMemoryRequirements( imageData->image.get() ).size );
imageGenerator( data, extent );
device->unmapMemory( needsStaging ? stagingBufferData->deviceMemory.get() : imageData->deviceMemory.get() );
if (needsStaging) if ( needsStaging )
{ {
// Since we're going to blit to the texture image, set its layout to eTransferDstOptimal // Since we're going to blit to the texture image, set its layout to eTransferDstOptimal
vk::su::setImageLayout(commandBuffer, imageData->image.get(), imageData->format, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal); vk::su::setImageLayout( commandBuffer,
vk::BufferImageCopy copyRegion(0, extent.width, extent.height, vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), vk::Extent3D(extent, 1)); imageData->image.get(),
commandBuffer->copyBufferToImage(stagingBufferData->buffer.get(), imageData->image.get(), vk::ImageLayout::eTransferDstOptimal, copyRegion); imageData->format,
vk::ImageLayout::eUndefined,
vk::ImageLayout::eTransferDstOptimal );
vk::BufferImageCopy copyRegion( 0,
extent.width,
extent.height,
vk::ImageSubresourceLayers( vk::ImageAspectFlagBits::eColor, 0, 0, 1 ),
vk::Offset3D( 0, 0, 0 ),
vk::Extent3D( extent, 1 ) );
commandBuffer->copyBufferToImage(
stagingBufferData->buffer.get(), imageData->image.get(), vk::ImageLayout::eTransferDstOptimal, copyRegion );
// Set the layout for the texture image from eTransferDstOptimal to SHADER_READ_ONLY // Set the layout for the texture image from eTransferDstOptimal to SHADER_READ_ONLY
vk::su::setImageLayout(commandBuffer, imageData->image.get(), imageData->format, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); vk::su::setImageLayout( commandBuffer,
imageData->image.get(),
imageData->format,
vk::ImageLayout::eTransferDstOptimal,
vk::ImageLayout::eShaderReadOnlyOptimal );
} }
else else
{ {
// If we can use the linear tiled image as a texture, just do it // If we can use the linear tiled image as a texture, just do it
vk::su::setImageLayout(commandBuffer, imageData->image.get(), imageData->format, vk::ImageLayout::ePreinitialized, vk::ImageLayout::eShaderReadOnlyOptimal); vk::su::setImageLayout( commandBuffer,
imageData->image.get(),
imageData->format,
vk::ImageLayout::ePreinitialized,
vk::ImageLayout::eShaderReadOnlyOptimal );
} }
} }
@ -264,59 +333,100 @@ namespace vk
struct UUID struct UUID
{ {
public: public:
UUID(uint8_t const data[VK_UUID_SIZE]); UUID( uint8_t const data[VK_UUID_SIZE] );
uint8_t m_data[VK_UUID_SIZE]; uint8_t m_data[VK_UUID_SIZE];
}; };
template <typename TargetType, typename SourceType> template <typename TargetType, typename SourceType>
VULKAN_HPP_INLINE TargetType checked_cast(SourceType value) VULKAN_HPP_INLINE TargetType checked_cast( SourceType value )
{ {
static_assert(sizeof(TargetType) <= sizeof(SourceType), "No need to cast from smaller to larger type!"); static_assert( sizeof( TargetType ) <= sizeof( SourceType ), "No need to cast from smaller to larger type!" );
static_assert(!std::numeric_limits<TargetType>::is_signed, "Only unsigned types supported!"); static_assert( !std::numeric_limits<TargetType>::is_signed, "Only unsigned types supported!" );
static_assert(!std::numeric_limits<SourceType>::is_signed, "Only unsigned types supported!"); static_assert( !std::numeric_limits<SourceType>::is_signed, "Only unsigned types supported!" );
assert(value <= std::numeric_limits<TargetType>::max()); assert( value <= std::numeric_limits<TargetType>::max() );
return static_cast<TargetType>(value); return static_cast<TargetType>( value );
} }
vk::UniqueDeviceMemory allocateMemory(vk::UniqueDevice const& device, vk::PhysicalDeviceMemoryProperties const& memoryProperties, vk::MemoryRequirements const& memoryRequirements, vk::UniqueDeviceMemory allocateMemory( vk::UniqueDevice const & device,
vk::MemoryPropertyFlags memoryPropertyFlags); vk::PhysicalDeviceMemoryProperties const & memoryProperties,
bool contains(std::vector<vk::ExtensionProperties> const& extensionProperties, std::string const& extensionName); vk::MemoryRequirements const & memoryRequirements,
vk::UniqueCommandPool createCommandPool(vk::UniqueDevice &device, uint32_t queueFamilyIndex); vk::MemoryPropertyFlags memoryPropertyFlags );
vk::UniqueDebugUtilsMessengerEXT createDebugUtilsMessenger(vk::UniqueInstance &instance); bool contains( std::vector<vk::ExtensionProperties> const & extensionProperties,
vk::UniqueDescriptorPool createDescriptorPool(vk::UniqueDevice &device, std::vector<vk::DescriptorPoolSize> const& poolSizes); std::string const & extensionName );
vk::UniqueDescriptorSetLayout createDescriptorSetLayout(vk::UniqueDevice const& device, std::vector<std::tuple<vk::DescriptorType, uint32_t, vk::ShaderStageFlags>> const& bindingData, vk::UniqueCommandPool createCommandPool( vk::UniqueDevice & device, uint32_t queueFamilyIndex );
vk::DescriptorSetLayoutCreateFlags flags = {}); vk::UniqueDebugUtilsMessengerEXT createDebugUtilsMessenger( vk::UniqueInstance & instance );
vk::UniqueDevice createDevice(vk::PhysicalDevice physicalDevice, uint32_t queueFamilyIndex, std::vector<std::string> const& extensions = {}, vk::PhysicalDeviceFeatures const* physicalDeviceFeatures = nullptr, void const* pNext = nullptr); vk::UniqueDescriptorPool createDescriptorPool( vk::UniqueDevice & device,
std::vector<vk::UniqueFramebuffer> createFramebuffers(vk::UniqueDevice &device, vk::UniqueRenderPass &renderPass, std::vector<vk::UniqueImageView> const& imageViews, vk::UniqueImageView const& depthImageView, vk::Extent2D const& extent); std::vector<vk::DescriptorPoolSize> const & poolSizes );
vk::UniquePipeline createGraphicsPipeline(vk::UniqueDevice const& device, vk::UniquePipelineCache const& pipelineCache, vk::UniqueDescriptorSetLayout createDescriptorSetLayout(
std::pair<vk::ShaderModule, vk::SpecializationInfo const*> const& vertexShaderData, vk::UniqueDevice const & device,
std::pair<vk::ShaderModule, vk::SpecializationInfo const*> const& fragmentShaderData, uint32_t vertexStride, std::vector<std::tuple<vk::DescriptorType, uint32_t, vk::ShaderStageFlags>> const & bindingData,
std::vector<std::pair<vk::Format, uint32_t>> const& vertexInputAttributeFormatOffset, vk::FrontFace frontFace, bool depthBuffered, vk::DescriptorSetLayoutCreateFlags flags = {} );
vk::UniquePipelineLayout const& pipelineLayout, vk::UniqueRenderPass const& renderPass); vk::UniqueDevice createDevice( vk::PhysicalDevice physicalDevice,
vk::UniqueInstance createInstance(std::string const& appName, std::string const& engineName, std::vector<std::string> const& layers = {}, std::vector<std::string> const& extensions = {}, uint32_t queueFamilyIndex,
uint32_t apiVersion = VK_API_VERSION_1_0); std::vector<std::string> const & extensions = {},
vk::UniqueRenderPass createRenderPass(vk::UniqueDevice &device, vk::Format colorFormat, vk::Format depthFormat, vk::AttachmentLoadOp loadOp = vk::AttachmentLoadOp::eClear, vk::ImageLayout colorFinalLayout = vk::ImageLayout::ePresentSrcKHR); vk::PhysicalDeviceFeatures const * physicalDeviceFeatures = nullptr,
VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, VkDebugUtilsMessengerCallbackDataEXT const * pCallbackData, void * /*pUserData*/); void const * pNext = nullptr );
uint32_t findGraphicsQueueFamilyIndex(std::vector<vk::QueueFamilyProperties> const& queueFamilyProperties); std::vector<vk::UniqueFramebuffer> createFramebuffers( vk::UniqueDevice & device,
std::pair<uint32_t, uint32_t> findGraphicsAndPresentQueueFamilyIndex(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR const& surface); vk::UniqueRenderPass & renderPass,
uint32_t findMemoryType(vk::PhysicalDeviceMemoryProperties const& memoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirementsMask); std::vector<vk::UniqueImageView> const & imageViews,
std::vector<std::string> getDeviceExtensions(); vk::UniqueImageView const & depthImageView,
std::vector<std::string> getInstanceExtensions(); vk::Extent2D const & extent );
vk::Format pickDepthFormat(vk::PhysicalDevice const& physicalDevice); vk::UniquePipeline
vk::PresentModeKHR pickPresentMode(std::vector<vk::PresentModeKHR> const& presentModes); createGraphicsPipeline( vk::UniqueDevice const & device,
vk::SurfaceFormatKHR pickSurfaceFormat(std::vector<vk::SurfaceFormatKHR> const& formats); vk::UniquePipelineCache const & pipelineCache,
void submitAndWait(vk::UniqueDevice &device, vk::Queue queue, vk::UniqueCommandBuffer &commandBuffer); std::pair<vk::ShaderModule, vk::SpecializationInfo const *> const & vertexShaderData,
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet, std::pair<vk::ShaderModule, vk::SpecializationInfo const *> const & fragmentShaderData,
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData, vk::su::TextureData const& textureData, uint32_t vertexStride,
uint32_t bindingOffset = 0); std::vector<std::pair<vk::Format, uint32_t>> const & vertexInputAttributeFormatOffset,
void updateDescriptorSets(vk::UniqueDevice const& device, vk::UniqueDescriptorSet const& descriptorSet, vk::FrontFace frontFace,
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const&, vk::UniqueBufferView const&>> const& bufferData, bool depthBuffered,
std::vector<vk::su::TextureData> const& textureData, uint32_t bindingOffset = 0); vk::UniquePipelineLayout const & pipelineLayout,
vk::UniqueRenderPass const & renderPass );
vk::UniqueInstance createInstance( std::string const & appName,
std::string const & engineName,
std::vector<std::string> const & layers = {},
std::vector<std::string> const & extensions = {},
uint32_t apiVersion = VK_API_VERSION_1_0 );
vk::UniqueRenderPass createRenderPass( vk::UniqueDevice & device,
vk::Format colorFormat,
vk::Format depthFormat,
vk::AttachmentLoadOp loadOp = vk::AttachmentLoadOp::eClear,
vk::ImageLayout colorFinalLayout = vk::ImageLayout::ePresentSrcKHR );
VKAPI_ATTR VkBool32 VKAPI_CALL
debugUtilsMessengerCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageTypes,
VkDebugUtilsMessengerCallbackDataEXT const * pCallbackData,
void * /*pUserData*/ );
uint32_t findGraphicsQueueFamilyIndex( std::vector<vk::QueueFamilyProperties> const & queueFamilyProperties );
std::pair<uint32_t, uint32_t> findGraphicsAndPresentQueueFamilyIndex( vk::PhysicalDevice physicalDevice,
vk::SurfaceKHR const & surface );
uint32_t findMemoryType( vk::PhysicalDeviceMemoryProperties const & memoryProperties,
uint32_t typeBits,
vk::MemoryPropertyFlags requirementsMask );
std::vector<std::string> getDeviceExtensions();
std::vector<std::string> getInstanceExtensions();
vk::Format pickDepthFormat( vk::PhysicalDevice const & physicalDevice );
vk::PresentModeKHR pickPresentMode( std::vector<vk::PresentModeKHR> const & presentModes );
vk::SurfaceFormatKHR pickSurfaceFormat( std::vector<vk::SurfaceFormatKHR> const & formats );
void submitAndWait( vk::UniqueDevice & device, vk::Queue queue, vk::UniqueCommandBuffer & commandBuffer );
void updateDescriptorSets(
vk::UniqueDevice const & device,
vk::UniqueDescriptorSet const & descriptorSet,
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const &, vk::UniqueBufferView const &>> const &
bufferData,
vk::su::TextureData const & textureData,
uint32_t bindingOffset = 0 );
void updateDescriptorSets(
vk::UniqueDevice const & device,
vk::UniqueDescriptorSet const & descriptorSet,
std::vector<std::tuple<vk::DescriptorType, vk::UniqueBuffer const &, vk::UniqueBufferView const &>> const &
bufferData,
std::vector<vk::su::TextureData> const & textureData,
uint32_t bindingOffset = 0 );
} } // namespace su
} } // namespace vk
std::ostream& operator<<(std::ostream& os, vk::su::UUID const& uuid); std::ostream & operator<<( std::ostream & os, vk::su::UUID const & uuid );

View File

@ -16,54 +16,61 @@
// Compile test on device functions // Compile test on device functions
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "DeviceFunctions"; static char const * AppName = "DeviceFunctions";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::ApplicationInfo appInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1); vk::ApplicationInfo appInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &appInfo)); vk::UniqueInstance instance = vk::createInstanceUnique( vk::InstanceCreateInfo( {}, &appInfo ) );
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
// get the QueueFamilyProperties of the first PhysicalDevice // get the QueueFamilyProperties of the first PhysicalDevice
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties(); std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
// get the first index into queueFamiliyProperties which supports graphics // get the first index into queueFamiliyProperties which supports graphics
size_t graphicsQueueFamilyIndex = std::distance(queueFamilyProperties.begin(), size_t graphicsQueueFamilyIndex = std::distance(
std::find_if(queueFamilyProperties.begin(), queueFamilyProperties.begin(),
queueFamilyProperties.end(), std::find_if(
[](vk::QueueFamilyProperties const& qfp) { return qfp.queueFlags & vk::QueueFlagBits::eGraphics; })); queueFamilyProperties.begin(), queueFamilyProperties.end(), []( vk::QueueFamilyProperties const & qfp ) {
assert(graphicsQueueFamilyIndex < queueFamilyProperties.size()); return qfp.queueFlags & vk::QueueFlagBits::eGraphics;
} ) );
assert( graphicsQueueFamilyIndex < queueFamilyProperties.size() );
// create a UniqueDevice // create a UniqueDevice
float queuePriority = 0.0f; float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), static_cast<uint32_t>(graphicsQueueFamilyIndex), 1, &queuePriority); vk::DeviceQueueCreateInfo deviceQueueCreateInfo(
vk::UniqueDevice device = physicalDevice.createDeviceUnique(vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo)); vk::DeviceQueueCreateFlags(), static_cast<uint32_t>( graphicsQueueFamilyIndex ), 1, &queuePriority );
vk::UniqueDevice device =
physicalDevice.createDeviceUnique( vk::DeviceCreateInfo( vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo ) );
std::vector<uint8_t> data; std::vector<uint8_t> data;
device->getAccelerationStructureHandleNV<uint8_t>({}, data, vk::DispatchLoaderDynamic()); device->getAccelerationStructureHandleNV<uint8_t>( {}, data, vk::DispatchLoaderDynamic() );
std::vector<vk::UniqueCommandBuffer>::allocator_type vectorAllocator; std::vector<vk::UniqueCommandBuffer>::allocator_type vectorAllocator;
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique({}, vectorAllocator, vk::DispatchLoaderStatic()).front()); vk::UniqueCommandBuffer commandBuffer =
std::move( device->allocateCommandBuffersUnique( {}, vectorAllocator, vk::DispatchLoaderStatic() ).front() );
commandBuffer->begin(nullptr); commandBuffer->begin( nullptr );
std::vector<vk::UniqueHandle<vk::CommandBuffer, vk::DispatchLoaderDynamic>>::allocator_type dynamicVectorAllocator; std::vector<vk::UniqueHandle<vk::CommandBuffer, vk::DispatchLoaderDynamic>>::allocator_type dynamicVectorAllocator;
vk::UniqueHandle<vk::CommandBuffer, vk::DispatchLoaderDynamic> dynamicCommandBuffer = std::move(device->allocateCommandBuffersUnique({}, dynamicVectorAllocator, vk::DispatchLoaderDynamic()).front()); vk::UniqueHandle<vk::CommandBuffer, vk::DispatchLoaderDynamic> dynamicCommandBuffer = std::move(
device->allocateCommandBuffersUnique( {}, dynamicVectorAllocator, vk::DispatchLoaderDynamic() ).front() );
} }
catch (vk::SystemError const& err) catch ( vk::SystemError const & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;

View File

@ -17,45 +17,46 @@
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#include <vulkan/vulkan.h>
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <vulkan/vulkan.h>
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::DynamicLoader dl; vk::DynamicLoader dl;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); dl.getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" );
VULKAN_HPP_DEFAULT_DISPATCHER.init( vkGetInstanceProcAddr );
vk::Instance instance = vk::createInstance({}, nullptr); vk::Instance instance = vk::createInstance( {}, nullptr );
// initialize function pointers for instance // initialize function pointers for instance
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance); VULKAN_HPP_DEFAULT_DISPATCHER.init( instance );
// create a dispatcher, based on additional vkDevice/vkGetDeviceProcAddr // create a dispatcher, based on additional vkDevice/vkGetDeviceProcAddr
std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices(); std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
assert(!physicalDevices.empty()); assert( !physicalDevices.empty() );
vk::Device device = physicalDevices[0].createDevice({}, nullptr); vk::Device device = physicalDevices[0].createDevice( {}, nullptr );
// function pointer specialization for device // function pointer specialization for device
VULKAN_HPP_DEFAULT_DISPATCHER.init(device); VULKAN_HPP_DEFAULT_DISPATCHER.init( device );
} }
catch (vk::SystemError const& err) catch ( vk::SystemError const & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;

View File

@ -16,39 +16,40 @@
// Compile test on using std::hash on handles // Compile test on using std::hash on handles
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
static char const* AppName = "Hash"; static char const * AppName = "Hash";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::ApplicationInfo appInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1); vk::ApplicationInfo appInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &appInfo)); vk::UniqueInstance instance = vk::createInstanceUnique( vk::InstanceCreateInfo( {}, &appInfo ) );
auto h1 = std::hash<vk::Instance>{}(*instance); auto h1 = std::hash<vk::Instance>{}( *instance );
auto h2 = std::hash<VkInstance>{}(*instance); auto h2 = std::hash<VkInstance>{}( *instance );
assert(h1 == h2); assert( h1 == h2 );
std::unordered_set<vk::Instance> uset; std::unordered_set<vk::Instance> uset;
uset.insert(*instance); uset.insert( *instance );
std::unordered_map<vk::Instance, size_t> umap; std::unordered_map<vk::Instance, size_t> umap;
umap[*instance] = 1; umap[*instance] = 1;
} }
catch (vk::SystemError const& err) catch ( vk::SystemError const & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;

View File

@ -20,47 +20,61 @@
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "NoExceptions"; static char const * AppName = "NoExceptions";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
vk::DynamicLoader dl; vk::DynamicLoader dl;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); dl.getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" );
VULKAN_HPP_DEFAULT_DISPATCHER.init( vkGetInstanceProcAddr );
vk::ApplicationInfo appInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1); vk::ApplicationInfo appInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &appInfo)).value; vk::UniqueInstance instance = vk::createInstanceUnique( vk::InstanceCreateInfo( {}, &appInfo ) ).value;
VULKAN_HPP_DEFAULT_DISPATCHER.init(*instance); VULKAN_HPP_DEFAULT_DISPATCHER.init( *instance );
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices().value; std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices().value;
assert(!physicalDevices.empty()); assert( !physicalDevices.empty() );
// get the QueueFamilyProperties of the first PhysicalDevice // get the QueueFamilyProperties of the first PhysicalDevice
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevices[0].getQueueFamilyProperties(); std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevices[0].getQueueFamilyProperties();
// get the first index into queueFamiliyProperties which supports graphics // get the first index into queueFamiliyProperties which supports graphics
size_t graphicsQueueFamilyIndex = std::distance(queueFamilyProperties.begin(), size_t graphicsQueueFamilyIndex = std::distance( queueFamilyProperties.begin(),
std::find_if(queueFamilyProperties.begin(), std::find_if( queueFamilyProperties.begin(),
queueFamilyProperties.end(), queueFamilyProperties.end(),
[](vk::QueueFamilyProperties const& qfp) { return qfp.queueFlags & vk::QueueFlagBits::eGraphics; })); []( vk::QueueFamilyProperties const & qfp ) {
assert(graphicsQueueFamilyIndex < queueFamilyProperties.size()); return qfp.queueFlags & vk::QueueFlagBits::eGraphics;
} ) );
assert( graphicsQueueFamilyIndex < queueFamilyProperties.size() );
// create a UniqueDevice // create a UniqueDevice
float queuePriority = 0.0f; float queuePriority = 0.0f;
vk::DeviceQueueCreateInfo deviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), static_cast<uint32_t>(graphicsQueueFamilyIndex), 1, &queuePriority); vk::DeviceQueueCreateInfo deviceQueueCreateInfo(
vk::UniqueDevice device = physicalDevices[0].createDeviceUnique(vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo)).value; vk::DeviceQueueCreateFlags(), static_cast<uint32_t>( graphicsQueueFamilyIndex ), 1, &queuePriority );
VULKAN_HPP_DEFAULT_DISPATCHER.init(*device); vk::UniqueDevice device =
physicalDevices[0]
.createDeviceUnique( vk::DeviceCreateInfo( vk::DeviceCreateFlags(), 1, &deviceQueueCreateInfo ) )
.value;
VULKAN_HPP_DEFAULT_DISPATCHER.init( *device );
// create a UniqueCommandPool to allocate a CommandBuffer from // create a UniqueCommandPool to allocate a CommandBuffer from
vk::UniqueCommandPool commandPool = device->createCommandPoolUnique(vk::CommandPoolCreateInfo(vk::CommandPoolCreateFlags(), deviceQueueCreateInfo.queueFamilyIndex)).value; vk::UniqueCommandPool commandPool = device
->createCommandPoolUnique( vk::CommandPoolCreateInfo(
vk::CommandPoolCreateFlags(), deviceQueueCreateInfo.queueFamilyIndex ) )
.value;
// allocate a CommandBuffer from the CommandPool // allocate a CommandBuffer from the CommandPool
vk::UniqueCommandBuffer commandBuffer = std::move(device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1)).value.front()); vk::UniqueCommandBuffer commandBuffer = std::move( device
->allocateCommandBuffersUnique( vk::CommandBufferAllocateInfo(
commandPool.get(), vk::CommandBufferLevel::ePrimary, 1 ) )
.value.front() );
return 0; return 0;
} }

View File

@ -18,15 +18,16 @@
#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#include "vulkan/vulkan.hpp" #include "vulkan/vulkan.hpp"
#include <iostream> #include <iostream>
static char const* AppName = "StructureChain"; static char const * AppName = "StructureChain";
static char const* EngineName = "Vulkan.hpp"; static char const * EngineName = "Vulkan.hpp";
#if defined(_MSC_VER) #if defined( _MSC_VER )
#pragma warning( disable : 4189 ) # pragma warning( disable : 4189 )
#elif defined(__GNUC__) #elif defined( __GNUC__ )
#pragma GCC diagnostic ignored "-Wunused-variable" # pragma GCC diagnostic ignored "-Wunused-variable"
#else #else
// unknow compiler... just ignore the warnings for yourselves ;) // unknow compiler... just ignore the warnings for yourselves ;)
#endif #endif
@ -34,93 +35,106 @@ static char const* EngineName = "Vulkan.hpp";
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
template <typename T> template <typename T>
void unused(T const&) void unused( T const & )
{} {}
int main(int /*argc*/, char ** /*argv*/) int main( int /*argc*/, char ** /*argv*/ )
{ {
try try
{ {
vk::DynamicLoader dl; vk::DynamicLoader dl;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"); PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); dl.getProcAddress<PFN_vkGetInstanceProcAddr>( "vkGetInstanceProcAddr" );
VULKAN_HPP_DEFAULT_DISPATCHER.init( vkGetInstanceProcAddr );
vk::ApplicationInfo appInfo(AppName, 1, EngineName, 1, VK_API_VERSION_1_1); vk::ApplicationInfo appInfo( AppName, 1, EngineName, 1, VK_API_VERSION_1_1 );
vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo({}, &appInfo)); vk::UniqueInstance instance = vk::createInstanceUnique( vk::InstanceCreateInfo( {}, &appInfo ) );
VULKAN_HPP_DEFAULT_DISPATCHER.init(*instance); VULKAN_HPP_DEFAULT_DISPATCHER.init( *instance );
vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front(); vk::PhysicalDevice physicalDevice = instance->enumeratePhysicalDevices().front();
// some valid StructureChains // some valid StructureChains
vk::StructureChain<vk::PhysicalDeviceProperties2> sc0; vk::StructureChain<vk::PhysicalDeviceProperties2> sc0;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties> sc1; vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties> sc1;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceMaintenance3Properties> sc2; vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceMaintenance3Properties> sc2;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDevicePushDescriptorPropertiesKHR> sc3; vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDevicePushDescriptorPropertiesKHR> sc3;
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties> sc4; vk::StructureChain<vk::PhysicalDeviceProperties2,
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties, vk::PhysicalDevicePushDescriptorPropertiesKHR> sc6; vk::PhysicalDeviceIDProperties,
vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties, vk::PhysicalDevicePushDescriptorPropertiesKHR> sc7; vk::PhysicalDeviceMaintenance3Properties>
sc4;
vk::StructureChain<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceIDProperties,
vk::PhysicalDevicePushDescriptorPropertiesKHR>
sc6;
vk::StructureChain<vk::PhysicalDeviceProperties2,
vk::PhysicalDeviceIDProperties,
vk::PhysicalDeviceMaintenance3Properties,
vk::PhysicalDevicePushDescriptorPropertiesKHR>
sc7;
// some invalid StructureChains // some invalid StructureChains
//vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties> x; // vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties> x;
//vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties, vk::PhysicalDevicePushDescriptorPropertiesKHR> x; // vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceMaintenance3Properties,
//vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDevicePushDescriptorPropertiesKHR, vk::PhysicalDeviceMaintenance3Properties> x; // vk::PhysicalDevicePushDescriptorPropertiesKHR> x; vk::StructureChain<vk::PhysicalDeviceIDProperties,
//vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceIDProperties> x; // vk::PhysicalDevicePushDescriptorPropertiesKHR, vk::PhysicalDeviceMaintenance3Properties> x;
//vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceProperties2> x; // vk::StructureChain<vk::PhysicalDeviceProperties2, vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceIDProperties>
// x; vk::StructureChain<vk::PhysicalDeviceIDProperties, vk::PhysicalDeviceProperties2> x;
// unlink a struct from a StructureChain // unlink a struct from a StructureChain
sc7.unlink<vk::PhysicalDeviceMaintenance3Properties>(); sc7.unlink<vk::PhysicalDeviceMaintenance3Properties>();
// some invalid unlink calls // some invalid unlink calls
//sc7.unlink<vk::PhysicalDeviceMaintenance3Properties>(); // assertion fires on trying to unlink some already unlinked structure // sc7.unlink<vk::PhysicalDeviceMaintenance3Properties>(); // assertion fires on trying to unlink some already
//sc7.unlink<vk::PhysicalDeviceProperties2>(); // unlinked structure sc7.unlink<vk::PhysicalDeviceProperties2>();
//sc1.unlink<vk::PhysicalDeviceMaintenance3Properties>(); // sc1.unlink<vk::PhysicalDeviceMaintenance3Properties>();
// re-link a struct // re-link a struct
sc7.relink<vk::PhysicalDeviceMaintenance3Properties>(); sc7.relink<vk::PhysicalDeviceMaintenance3Properties>();
// invalid re-linking // invalid re-linking
//sc7.relink<vk::PhysicalDeviceProperties2>(); // sc7.relink<vk::PhysicalDeviceProperties2>();
//sc1.relink<vk::PhysicalDeviceMaintenance3Properties>(); // sc1.relink<vk::PhysicalDeviceMaintenance3Properties>();
//sc1.relink<vk::PhysicalDeviceIDProperties>(); // assertion fires on trying to relink some structure that hasn't been unlinked // sc1.relink<vk::PhysicalDeviceIDProperties>(); // assertion fires on trying to relink some structure
// that hasn't been unlinked
// simple call, passing structures in // simple call, passing structures in
vk::PhysicalDeviceFeatures2 pdf; vk::PhysicalDeviceFeatures2 pdf;
physicalDevice.getFeatures2(&pdf); physicalDevice.getFeatures2( &pdf );
// simple calls, getting structure back // simple calls, getting structure back
vk::PhysicalDeviceFeatures2 a = physicalDevice.getFeatures2(); vk::PhysicalDeviceFeatures2 a = physicalDevice.getFeatures2();
unused(a); unused( a );
// complex calls, getting StructureChain back // complex calls, getting StructureChain back
auto c = physicalDevice.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>(); auto c = physicalDevice.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>();
vk::PhysicalDeviceFeatures2 & c0 = c.get<vk::PhysicalDeviceFeatures2>(); vk::PhysicalDeviceFeatures2 & c0 = c.get<vk::PhysicalDeviceFeatures2>();
unused(c0); unused( c0 );
auto t0 = c.get<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>(); auto t0 = c.get<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>();
unused(t0); unused( t0 );
auto d = physicalDevice.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>(); auto d = physicalDevice.getFeatures2<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>();
vk::PhysicalDeviceFeatures2 & d0 = d.get<vk::PhysicalDeviceFeatures2>(); vk::PhysicalDeviceFeatures2 & d0 = d.get<vk::PhysicalDeviceFeatures2>();
unused(d0); unused( d0 );
vk::PhysicalDeviceVariablePointerFeatures & d1 = d.get<vk::PhysicalDeviceVariablePointerFeatures>(); vk::PhysicalDeviceVariablePointerFeatures & d1 = d.get<vk::PhysicalDeviceVariablePointerFeatures>();
unused(d1); unused( d1 );
auto t1 = d.get<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>(); auto t1 = d.get<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVariablePointerFeatures>();
unused(t1); unused( t1 );
using StructureChain = vk::StructureChain<vk::QueueFamilyProperties2, vk::QueueFamilyCheckpointPropertiesNV>; using StructureChain = vk::StructureChain<vk::QueueFamilyProperties2, vk::QueueFamilyCheckpointPropertiesNV>;
using AllocatorType = std::vector<StructureChain>::allocator_type; using AllocatorType = std::vector<StructureChain>::allocator_type;
auto qfd = physicalDevice.getQueueFamilyProperties2<StructureChain, AllocatorType>(VULKAN_HPP_DEFAULT_DISPATCHER); auto qfd = physicalDevice.getQueueFamilyProperties2<StructureChain, AllocatorType>( VULKAN_HPP_DEFAULT_DISPATCHER );
unused(qfd); unused( qfd );
} }
catch (vk::SystemError const& err) catch ( vk::SystemError const & err )
{ {
std::cout << "vk::SystemError: " << err.what() << std::endl; std::cout << "vk::SystemError: " << err.what() << std::endl;
exit(-1); exit( -1 );
} }
catch (...) catch ( ... )
{ {
std::cout << "unknown error\n"; std::cout << "unknown error\n";
exit(-1); exit( -1 );
} }
return 0; return 0;
} }

View File

@ -21,11 +21,11 @@
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#if defined(__x86_64__) || defined(_M_X64) #if defined( __x86_64__ ) || defined( _M_X64 )
// On 32-bit systems the test is ambiguous. // On 32-bit systems the test is ambiguous.
void test() void test()
{ {
VkSurfaceKHR surface = 0; VkSurfaceKHR surface = 0;
auto uniqueSurface = vk::UniqueSurfaceKHR(surface, vk::Instance()); auto uniqueSurface = vk::UniqueSurfaceKHR( surface, vk::Instance() );
} }
#endif #endif

File diff suppressed because it is too large Load Diff