Adding support for functions with a const pointer input with its len specified by a structure member.

This commit is contained in:
asuessenbach 2020-10-28 10:18:05 +01:00
parent cf92bfea25
commit 50cc580941
2 changed files with 117 additions and 65 deletions

View File

@ -1128,7 +1128,7 @@ void VulkanHppGenerator::appendCommand( std::string & str,
appendedFunction = true; appendedFunction = true;
} }
} }
else if ( ( ( isParamIndirect( commandData.params[returnVectorParamIt->first].len, else if ( ( ( isLenByStructMember( commandData.params[returnVectorParamIt->first].len,
commandData.params[returnVectorParamIt->second] ) ) ) && commandData.params[returnVectorParamIt->second] ) ) ) &&
( vectorParamIndices.size() == 1 ) ) ( vectorParamIndices.size() == 1 ) )
{ {
@ -1145,7 +1145,8 @@ void VulkanHppGenerator::appendCommand( std::string & str,
if ( returnVectorParamIt == vectorParamIndices.end() ) if ( returnVectorParamIt == vectorParamIndices.end() )
{ {
// provide standard, enhanced, and chained call // provide standard, enhanced, and chained call
appendCommandChained( str, name, commandData, definition, nonConstPointerParamIndices[0] ); appendCommandChained(
str, name, commandData, definition, vectorParamIndices, nonConstPointerParamIndices[0] );
appendedFunction = true; appendedFunction = true;
} }
} }
@ -1281,6 +1282,7 @@ void VulkanHppGenerator::appendCommandChained( std::string & str,
std::string const & name, std::string const & name,
CommandData const & commandData, CommandData const & commandData,
bool definition, bool definition,
std::map<size_t, size_t> const & vectorParamIndices,
size_t nonConstPointerIndex ) const size_t nonConstPointerIndex ) const
{ {
assert( ( commandData.returnType == "VkResult" ) || ( commandData.returnType == "void" ) ); assert( ( commandData.returnType == "VkResult" ) || ( commandData.returnType == "void" ) );
@ -1296,12 +1298,12 @@ ${leave})";
std::string enter, leave; std::string enter, leave;
std::tie( enter, leave ) = generateProtection( commandData.feature, commandData.extensions ); std::tie( enter, leave ) = generateProtection( commandData.feature, commandData.extensions );
str += str += replaceWithMap(
replaceWithMap( functionTemplate, functionTemplate,
std::map<std::string, std::string>( std::map<std::string, std::string>(
{ { "commandEnhanced", { { "commandEnhanced",
( commandData.returnType == "void" ) ( commandData.returnType == "void" )
? constructCommandVoidGetValue( name, commandData, definition, nonConstPointerIndex ) ? constructCommandVoidGetValue( name, commandData, definition, vectorParamIndices, nonConstPointerIndex )
: constructCommandResultGetValue( name, commandData, definition, nonConstPointerIndex ) }, : constructCommandResultGetValue( name, commandData, definition, nonConstPointerIndex ) },
{ "commandEnhancedChained", { "commandEnhancedChained",
( commandData.returnType == "void" ) ( commandData.returnType == "void" )
@ -1421,7 +1423,8 @@ ${leave})";
case 1: case 1:
commandEnhanced = commandEnhanced =
( commandData.returnType == "void" ) ( commandData.returnType == "void" )
? constructCommandVoidGetValue( name, commandData, definition, nonConstPointerParamIndices[0] ) ? constructCommandVoidGetValue(
name, commandData, definition, vectorParamIndices, nonConstPointerParamIndices[0] )
: constructCommandResultGetValue( name, commandData, definition, nonConstPointerParamIndices[0] ); : constructCommandResultGetValue( name, commandData, definition, nonConstPointerParamIndices[0] );
break; break;
} }
@ -3087,11 +3090,11 @@ std::string VulkanHppGenerator::constructArgumentListEnhanced( std::vector<Param
if ( i == singularParam ) if ( i == singularParam )
{ {
assert( params[i].type.isConstPointer() && !params[i].len.empty() && assert( params[i].type.isConstPointer() && !params[i].len.empty() &&
!isParamIndirect( params[i].len, params ) && beginsWith( params[i].type.type, "Vk" ) ); !isLenByStructMember( params[i].len, params ) && beginsWith( params[i].type.type, "Vk" ) );
argumentList += "const " + stripPrefix( params[i].type.type, "Vk" ) + " & " + argumentList += "const " + stripPrefix( params[i].type.type, "Vk" ) + " & " +
stripPluralS( startLowerCase( stripPrefix( params[i].name, "p" ) ) ); stripPluralS( startLowerCase( stripPrefix( params[i].name, "p" ) ) );
} }
else if ( params[i].type.isConstPointer() && !isParamIndirect( params[i].len, params ) ) else if ( params[i].type.isConstPointer() )
{ {
std::string name = startLowerCase( stripPrefix( params[i].name, "p" ) ); std::string name = startLowerCase( stripPrefix( params[i].name, "p" ) );
if ( params[i].len.empty() ) if ( params[i].len.empty() )
@ -3236,6 +3239,12 @@ std::string VulkanHppGenerator::constructCallArgument( ParamData const & param,
// very special handling for some types, which originally gets in as a pointer, but is mapped to a reference // very special handling for some types, which originally gets in as a pointer, but is mapped to a reference
argument = "&" + param.name; argument = "&" + param.name;
} }
else if ( enhanced && ( param.len.find( "->" ) != std::string::npos ) )
{
assert( param.type.isConstPointer() );
assert( !beginsWith( param.type.type, "Vk" ) );
argument = startLowerCase( stripPrefix( param.name, "p" ) ) + ".data()";
}
else else
{ {
argument = param.name; argument = param.name;
@ -5170,29 +5179,67 @@ std::string VulkanHppGenerator::constructCommandVoidGetChain( std::string const
std::string VulkanHppGenerator::constructCommandVoidGetValue( std::string const & name, std::string VulkanHppGenerator::constructCommandVoidGetValue( std::string const & name,
CommandData const & commandData, CommandData const & commandData,
bool definition, bool definition,
size_t nonConstPointerIndex ) const std::map<size_t, size_t> const & vectorParamIndices,
size_t returnParamIndex ) const
{ {
assert( ( commandData.returnType == "void" ) && commandData.successCodes.empty() && commandData.errorCodes.empty() ); assert( ( commandData.returnType == "void" ) && commandData.successCodes.empty() && commandData.errorCodes.empty() );
assert( vectorParamIndices.size() <= 1 );
assert( vectorParamIndices.empty() || ( vectorParamIndices.find( returnParamIndex ) == vectorParamIndices.end() ) );
assert( vectorParamIndices.empty() || ( vectorParamIndices.begin()->second != INVALID_INDEX ) );
std::set<size_t> skippedParameters = std::set<size_t> skippedParameters =
determineSkippedParams( commandData.handle, commandData.params, {}, { nonConstPointerIndex }, false ); determineSkippedParams( commandData.handle, commandData.params, {}, { returnParamIndex }, false );
std::string argumentList = std::string argumentList =
constructArgumentListEnhanced( commandData.params, skippedParameters, INVALID_INDEX, definition, false, false ); constructArgumentListEnhanced( commandData.params, skippedParameters, INVALID_INDEX, definition, false, false );
std::string commandName = determineCommandName( name, commandData.params[0].type.type ); std::string commandName = determineCommandName( name, commandData.params[0].type.type );
std::string nodiscard = determineNoDiscard( 1 < commandData.successCodes.size(), 1 < commandData.errorCodes.size() ); std::string nodiscard = determineNoDiscard( 1 < commandData.successCodes.size(), 1 < commandData.errorCodes.size() );
std::string returnType = commandData.params[nonConstPointerIndex].type.type; std::string returnType = commandData.params[returnParamIndex].type.type;
if ( beginsWith( returnType, "Vk" ) ) if ( beginsWith( returnType, "Vk" ) )
{ {
returnType = "VULKAN_HPP_NAMESPACE::" + stripPrefix( returnType, "Vk" ); returnType = "VULKAN_HPP_NAMESPACE::" + stripPrefix( returnType, "Vk" );
} }
bool needsVectorSizeCheck =
!vectorParamIndices.empty() && isLenByStructMember( commandData.params[vectorParamIndices.begin()->first].len,
commandData.params[vectorParamIndices.begin()->second] );
std::string noexceptString = needsVectorSizeCheck ? "VULKAN_HPP_NOEXCEPT_WHEN_NO_EXCEPTIONS" : "VULKAN_HPP_NOEXCEPT";
if ( definition ) if ( definition )
{ {
std::string className = commandData.handle.empty() ? "" : stripPrefix( commandData.handle, "Vk" );
std::string classSeparator = commandData.handle.empty() ? "" : "::";
std::string vectorSizeCheck;
if ( needsVectorSizeCheck )
{
std::string const sizeCheckTemplate =
R"(
#ifdef VULKAN_HPP_NO_EXCEPTIONS
VULKAN_HPP_ASSERT( ${vectorName}.size() == ${sizeValue} );
#else
if ( ${vectorName}.size() != ${sizeValue} )
{
throw LogicError( VULKAN_HPP_NAMESPACE_STRING "::${className}${classSeparator}${commandName}: ${vectorName}.size() != ${sizeValue}" );
}
#endif /*VULKAN_HPP_NO_EXCEPTIONS*/)";
std::vector<std::string> lenParts = tokenize( commandData.params[vectorParamIndices.begin()->first].len, "->" );
assert( lenParts.size() == 2 );
vectorSizeCheck = replaceWithMap(
sizeCheckTemplate,
{ { "className", className },
{ "classSeparator", classSeparator },
{ "commandName", commandName },
{ "sizeValue", startLowerCase( stripPrefix( lenParts[0], "p" ) ) + "." + lenParts[1] },
{ "vectorName",
startLowerCase( stripPrefix( commandData.params[vectorParamIndices.begin()->first].name, "p" ) ) } } );
}
std::string const functionTemplate = std::string const functionTemplate =
R"( template <typename Dispatch> R"( template <typename Dispatch>
VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE ${returnType} ${className}${classSeparator}${commandName}( ${argumentList} ) const VULKAN_HPP_NOEXCEPT VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE ${returnType} ${className}${classSeparator}${commandName}( ${argumentList} ) const ${noexcept}
{ {${vectorSizeCheck}
${returnType} ${returnVariable}; ${returnType} ${returnVariable};
d.${vkCommand}( ${callArguments} ); d.${vkCommand}( ${callArguments} );
return ${returnVariable}; return ${returnVariable};
@ -5201,24 +5248,27 @@ std::string VulkanHppGenerator::constructCommandVoidGetValue( std::string const
return replaceWithMap( return replaceWithMap(
functionTemplate, functionTemplate,
{ { "argumentList", argumentList }, { { "argumentList", argumentList },
{ "callArguments", { "callArguments", constructCallArgumentsGetValue( commandData.handle, commandData.params, returnParamIndex ) },
constructCallArgumentsGetValue( commandData.handle, commandData.params, nonConstPointerIndex ) }, { "className", className },
{ "className", commandData.handle.empty() ? "" : stripPrefix( commandData.handle, "Vk" ) }, { "classSeparator", classSeparator },
{ "classSeparator", commandData.handle.empty() ? "" : "::" },
{ "commandName", commandName }, { "commandName", commandName },
{ "noexcept", noexceptString },
{ "returnType", returnType }, { "returnType", returnType },
{ "returnVariable", startLowerCase( stripPrefix( commandData.params[nonConstPointerIndex].name, "p" ) ) }, { "returnVariable", startLowerCase( stripPrefix( commandData.params[returnParamIndex].name, "p" ) ) },
{ "vectorSizeCheck", vectorSizeCheck },
{ "vkCommand", name } } ); { "vkCommand", name } } );
} }
else else
{ {
std::string const functionTemplate = std::string const functionTemplate =
R"( template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE> R"( template <typename Dispatch = VULKAN_HPP_DEFAULT_DISPATCHER_TYPE>
VULKAN_HPP_NODISCARD ${returnType} ${commandName}( ${argumentList} ) const VULKAN_HPP_NOEXCEPT;)"; VULKAN_HPP_NODISCARD ${returnType} ${commandName}( ${argumentList} ) const ${noexcept};)";
return replaceWithMap( return replaceWithMap( functionTemplate,
functionTemplate, { { "argumentList", argumentList },
{ { "argumentList", argumentList }, { "commandName", commandName }, { "returnType", returnType } } ); { "commandName", commandName },
{ "noexcept", noexceptString },
{ "returnType", returnType } } );
} }
} }
@ -6800,7 +6850,7 @@ std::map<size_t, size_t>
if ( !it->len.empty() ) if ( !it->len.empty() )
{ {
auto findIt = std::find_if( params.begin(), it, [this, &it]( ParamData const & pd ) { auto findIt = std::find_if( params.begin(), it, [this, &it]( ParamData const & pd ) {
return ( pd.name == it->len ) || isParamIndirect( it->len, pd ); return ( pd.name == it->len ) || isLenByStructMember( it->len, pd );
} ); } );
if ( findIt < it ) if ( findIt < it )
@ -7129,13 +7179,7 @@ bool VulkanHppGenerator::isHandleType( std::string const & type ) const
return false; return false;
} }
bool VulkanHppGenerator::isParam( std::string const & name, std::vector<ParamData> const & params ) const bool VulkanHppGenerator::isLenByStructMember( std::string const & name, std::vector<ParamData> const & params ) const
{
return std::find_if( params.begin(), params.end(), [&name]( ParamData const & pd ) { return pd.name == name; } ) !=
params.end();
}
bool VulkanHppGenerator::isParamIndirect( std::string const & name, std::vector<ParamData> const & params ) const
{ {
// check if name specifies a member of a struct // check if name specifies a member of a struct
std::vector<std::string> nameParts = tokenize( name, "->" ); std::vector<std::string> nameParts = tokenize( name, "->" );
@ -7164,7 +7208,7 @@ bool VulkanHppGenerator::isParamIndirect( std::string const & name, std::vector<
return false; return false;
} }
bool VulkanHppGenerator::isParamIndirect( std::string const & name, ParamData const & param ) const bool VulkanHppGenerator::isLenByStructMember( std::string const & name, ParamData const & param ) const
{ {
// check if name specifies a member of a struct // check if name specifies a member of a struct
std::vector<std::string> nameParts = tokenize( name, "->" ); std::vector<std::string> nameParts = tokenize( name, "->" );
@ -7188,6 +7232,12 @@ bool VulkanHppGenerator::isParamIndirect( std::string const & name, ParamData co
return false; return false;
} }
bool VulkanHppGenerator::isParam( std::string const & name, std::vector<ParamData> const & params ) const
{
return std::find_if( params.begin(), params.end(), [&name]( ParamData const & pd ) { return pd.name == name; } ) !=
params.end();
}
bool VulkanHppGenerator::isStructureChainAnchor( std::string const & type ) const bool VulkanHppGenerator::isStructureChainAnchor( std::string const & type ) const
{ {
if ( beginsWith( type, "Vk" ) ) if ( beginsWith( type, "Vk" ) )
@ -7482,7 +7532,7 @@ VulkanHppGenerator::ParamData VulkanHppGenerator::readCommandParam( tinyxml2::XM
{ {
paramData.len = attribute.second; paramData.len = attribute.second;
check( ( paramData.len == "null-terminated" ) || isParam( paramData.len, params ) || check( ( paramData.len == "null-terminated" ) || isParam( paramData.len, params ) ||
isParamIndirect( paramData.len, params ), isLenByStructMember( paramData.len, params ),
line, line,
"command param len <" + paramData.len + "> is not recognized as a valid len value" ); "command param len <" + paramData.len + "> is not recognized as a valid len value" );
} }

View File

@ -316,6 +316,7 @@ private:
std::string const & name, std::string const & name,
CommandData const & commandData, CommandData const & commandData,
bool definition, bool definition,
std::map<size_t, size_t> const & vectorParamIndices,
size_t nonConstPointerIndex ) const; size_t nonConstPointerIndex ) const;
void appendCommandSingular( std::string & str, void appendCommandSingular( std::string & str,
std::string const & name, std::string const & name,
@ -599,7 +600,8 @@ private:
std::string constructCommandVoidGetValue( std::string const & name, std::string constructCommandVoidGetValue( std::string const & name,
CommandData const & commandData, CommandData const & commandData,
bool definition, bool definition,
size_t nonConstPointerIndex ) const; std::map<size_t, size_t> const & vectorParamIndices,
size_t returnParamIndex ) const;
std::string constructConstexprString( std::pair<std::string, StructureData> const & structData ) const; std::string constructConstexprString( std::pair<std::string, StructureData> const & structData ) const;
std::string constructFunctionBodyEnhanced( std::string const & indentation, std::string constructFunctionBodyEnhanced( std::string const & indentation,
std::string const & name, std::string const & name,
@ -666,9 +668,9 @@ private:
std::map<size_t, size_t> const & vectorParamIndices, std::map<size_t, size_t> const & vectorParamIndices,
size_t returnParamIndex ) const; size_t returnParamIndex ) const;
bool isHandleType( std::string const & type ) const; bool isHandleType( std::string const & type ) const;
bool isLenByStructMember( std::string const & name, std::vector<ParamData> const & params ) const;
bool isLenByStructMember( std::string const & name, ParamData const & param ) const;
bool isParam( std::string const & name, std::vector<ParamData> const & params ) const; bool isParam( std::string const & name, std::vector<ParamData> const & params ) const;
bool isParamIndirect( std::string const & name, std::vector<ParamData> const & params ) const;
bool isParamIndirect( std::string const & name, ParamData const & param ) const;
bool isStructureChainAnchor( std::string const & type ) const; bool isStructureChainAnchor( std::string const & type ) const;
bool needsComplexBody( CommandData const & commandData ) const; bool needsComplexBody( CommandData const & commandData ) const;
std::pair<bool, std::map<size_t, std::vector<size_t>>> std::pair<bool, std::map<size_t, std::vector<size_t>>>