How to enable VK_KHR_maintenance2 vulkan - vulkan

I'm trying to create VkImageView which will be binded to index 0.
Here is my VkImageView creation code
void Image::createImageView() {
VkImageViewUsageCreateInfo imageViewUsage;
imageViewUsage.sType=VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;
imageViewUsage.pNext=nullptr;
imageViewUsage.usage=VK_IMAGE_USAGE_STORAGE_BIT;
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.pNext=&imageViewUsage;
viewInfo.image = textureImage;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(device, &viewInfo, nullptr, &textureImageView) != VK_SUCCESS) {
throw std::runtime_error("failed to create texture image view!");
}
}
When I call vkUpdateDescriptorSets I get validation error:
vkCreateImageView: Includes a pNext pointer (pCreateInfo->pNext) to a VkStructureType (VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO), but its parent extension VK_KHR_maintenance2 has not been enabled. The Vulkan spec states: Each pNext member of any structure (including this one) in the pNext chain must be either NULL or a pointer to a valid instance of VkImageViewASTCDecodeModeEXT, VkImageViewUsageCreateInfo, VkSamplerYcbcrConversionInfo, VkVideoProfileKHR, or VkVideoProfilesKHR
Before this I had set viewInfo.pNext=nullptr; for which I was getting validation error:
Write update to VkDescriptorSet 0xf018750000000004[] allocated with VkDescriptorSetLayout 0x683e70000000002[] binding #0 failed with error message: Attempted write update to image descriptor failed due to: ImageView (VkImageView 0xa3c6870000000008[]) with usage mask 0x6 being used for a descriptor update of type VK_DESCRIPTOR_TYPE_STORAGE_IMAGE does not have VK_IMAGE_USAGE_STORAGE_BIT set
Can someone please help me with some hint how exactly I can solve the error?

The error message tells you exactly what to do. If you use VkImageViewUsageCreateInfo, that means you have to enable maintenance2 extension or in turn Vulkan 1.1 to which it was promoted.
Since you seem surprised by the existence of extensions, it feels likely your use of them is just accidental. You might simply want to stop using the VkImageViewUsageCreateInfo extension struct and always set pNext to NULL.

Related

What's the difference between Vulkan's descriptor set layouts and `VkWriteDescriptorInfo`?

I'm following the Vulkan tutorial about uniform buffers and I'm confused as to why we need to provide descriptor set layouts where all the informations they provide seem to already be in the VkWriteDescriptorSet structures with pass in to function vkUpdateDescriptorSets.
Why does Vulkan need both pieces of information and not just what we provide through vkUpdateDescriptorSets?
From the tutorial's code:
VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptorWrite.dstSet = descriptorSets[i];
descriptorWrite.dstBinding = 0;
descriptorWrite.dstArrayElement = 0;
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptorWrite.descriptorCount = 1;
descriptorWrite.pBufferInfo = &bufferInfo;
void createDescriptorSetLayout() {
VkDescriptorSetLayoutBinding uboLayoutBinding{};
uboLayoutBinding.binding = 0;
uboLayoutBinding.descriptorCount = 1;
uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uboLayoutBinding.pImmutableSamplers = nullptr;
uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
VkDescriptorSetLayoutCreateInfo layoutInfo{};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layoutInfo.bindingCount = 1;
layoutInfo.pBindings = &uboLayoutBinding;
if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor set layout!");
}
}
You need a descriptor set layout before you write to a descriptor set for the same reason you need a class before you can instantiate it. You can't do A a; for some type A before you define what A is. VkWriteDescriptorSet is like doing a.x = whatever; it doesn't make sense until you know what a is, and that requires having the class definition for A.
Descriptor set layouts define what a descriptor set looks like. It specifies all of the things that go into one. vkAllocateDescriptorSets is how you create an instance of a descriptor set layout (in our analogy, it's A a;, with the set being a). VkWriteDescriptorSet is how you provide the data that goes into a descriptor set (in our analogy, it's like a.x = whatever;, only potentially for multiple members).
VkWriteDescrptorSet has a lot of data that is redundantly specified in the descriptor set layout so that the implementation does not have to store the set layout as raw data.
Let's say that binding 2 in a descriptor set is a UBO of length X. And you want to attack a buffer range to that UBO descriptor. To do that, the implementation may need to know that it is a UBO descriptor and what its length is. If it does need to know that, then it would also need to store that information inside the descriptor set.
That forces the implementation to store extra data that's only useful for writing to the descriptor. If that descriptor is only set once and never again or otherwise modified infrequently (as descriptors often are), the implementation has to keep a bunch of information around for no reason.
So Vulkan makes you decide whether to keep the information around or not.

Check a kernel extension is loaded

I have to implement a function that installs a new kernel extension in the system. Before installing the extension I want to check whether it is already installed from another location. Since I do not know the other location I cannot use the sysconfig library function.
I've checked
truss genkex
to see how this is done by another tool. The only system call that was a bit interesting was read_sysconfig. Unfortunately I did not find documentation.
Any ideas?
Here I have an example function, that prints all loaded kernel extensions:
#define BUFF_SIZE 10241024U
static void testExtension() {
void *buffer = calloc( 1, BUFF_SIZE );
if( buffer ) {
struct ld_info *xInfo;
int result = loadquery(L_GETKERNINFO, buffer, BUFF_SIZE);
xInfo = buffer;
while( xInfo ) {
printf( ">>>>>>> >%s< %d\n", xInfo->ldinfo_filename, result );
uint offset = xInfo->ldinfo_next;
xInfo = offset ? (char*)xInfo + offset : NULL;
}
free( buffer );
}
}
The function you search for is SYS_QUERYLOAD sysconfig operation and here you can find more information about it
The SYS_QUERYLOAD sysconfig operation performs a query operation to
determine if a given object file has been loaded. This object file is
specified by the path field in the cfg_load structure passed in with
the parmp parameter. This operation utilizes the same cfg_load
structure that is specified for the SYS_KLOAD (SYS_KLOAD sysconfig
Operation) operation.
If the specified object file is not loaded, the kmid field in the
cfg_load structure is set to a value of 0 on return. Otherwise, the
kernel module ID of the module is returned in the kmid field. If
multiple instances of the module have been loaded into the kernel, the
module ID of the one most recently loaded is returned.
The libpath field in the cfg_load structure is not used for this
option.
Also you can check with this script about the objects in odm database.
for i in 1 2 3
do
odmget -q phase=$i Config_Rules
done
And check the file /sbin/rc.boot (which may contain load of some module(s)

vkCreateShaderModule doesn't fail, even when pCode doesn't point to valid SPIR-V code

By the documentation, the pCode field of the VkShaderModuleCreateInfo struct
must point to valid SPIR-V code, formatted and packed as described by the Khronos SPIR-V Specification.
Now, I've made a typo in the call of the following utility function and unintendedly provided the file name of the GLSL code as the shader_file_name.
void create_shader_module(VkDevice device, std::string const& shader_file_name)
{
std::ifstream shader_file(shader_file_name, std::ios::binary);
shader_file.seekg(0, std::ios_base::end);
std::size_t const shader_file_size = shader_file.tellg();
if (shader_file_size > 0)
{
assert(shader_file_size % sizeof(std::uint32_t) == 0);
std::vector<char> binary(shader_file_size);
shader_file.seekg(0, std::ios_base::beg);
shader_file.read(binary.data(), shader_file_size);
VkShaderModuleCreateInfo shader_module_create_info{};
shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shader_module_create_info.codeSize = shader_file_size;
shader_module_create_info.pCode = reinterpret_cast<std::uint32_t const*>(binary.data());
VkShaderModule shader_module;
if (vkCreateShaderModule(device, &shader_module_create_info, nullptr, &shader_module) != VK_SUCCESS)
throw std::exception("Could not create shader module");
}
}
Despite the typo, the code didn't throw, i.e. vkCreateShaderModule returned VK_SUCCESS. Why?
(Note that a subsequent call to vkCreateGraphicsPipelines with a VkPipelineShaderStageCreateInfo which uses the generated shader module fails.)
The validation layers would have found this problem, emitting a message:
SPIR-V module not valid: Invalid SPIR-V magic number.
Ths validation layers run the SPIR-V validator at vkCreateShaderModule time.
You are using Vulkan, not OpenGL. In Vulkan, it is not up to the implementation to validate your SPIR-V code. The Valid Usage for vkCreateShaderModule says that "pCode must point to valid SPIR-V code, formatted and packed as described by the
Khronos SPIR-V Specification." As with any other Valid Usage statement, if you violate it, the implementation will not tell you that you have done so.
You simply get undefined behavior.

Get generic type using Mono embedded

How to I create a generic List<String> object using mono embedded calls? I can get List's MonoClass:
MonoClass* list = mono_class_from_name(mscorlibimage,
"System.Collections.Generic", "List`1");
and I see in docs that there's
mono_class_from_generic_parameter(MonoGenericParam*...)
but I have no idea where and how to get the MonoGenericParam. Or perhaps I need to construct a valid name for mono_class_from_name? I think this can be a bit slower but I'd accept that for now. I tried
MonoClass* list = mono_class_from_name(mscorlib::get().image, "System.Collections.Generic", "List`1[System.String]");
but no luck.
UPDATE:
OK I found a way. Still I'd like to see if there's an official way of doing thing, as this hack looks too dirty to me.
Basically I searched mono sources for generic methods and found mono_class_bind_generic_parameters (see https://raw.github.com/mono/mono/master/mono/metadata/reflection.c). I had to link to libmono-2.0.a in addition to .so to use it. But it worked:
extern "C" MonoClass*
mono_class_bind_generic_parameters(MonoClass *klass,
int type_argc, MonoType **types, bool is_dynamic);
MonoClass* list = mono_class_from_name(mscorlib::get().image,
"System.Collections.Generic", "List`1");
MonoClass* strcls = mono_class_from_name(mscorlib::get().image, "System", "String");
printf("str class: %p\n", strcls);
MonoType* strtype = mono_class_get_type(strcls);
printf("str type: %p\n", strtype);
MonoType* types[1];
types[0] = strtype;
list = mono_class_bind_generic_parameters(list, 1, types, false);
printf("list[string] class: %p\n", list);
MonoObject* obj = mono_object_new(domain, list);
printf("list[string] created: %p\n", obj);
I suppose I can take sources (UPDATE: hardly so) of these methods and reimplement them (they parse metadata, etc) - if I don't want to link to .a - but I wonder if there's a simpler way. Mono docs just don't answer anything, as they use to.
UPDATE: found this thread: http://mono.1490590.n4.nabble.com/Embedded-API-Method-signature-not-found-with-generic-parameter-td4660157.html which seems to say that no embedded API exists for what I want (i.e. they do not bother to expose mono_class_bind_generic_parameters). Can someone prove that it's correct? With that method, by the way, I get MonoReflectionType* and no way to get back MonoType* from it - while it is as easy to as getting ->type from the structure - which is internal and access via functions to it is internal. Mono Embedded should be called "Mono Internal" instead.
UPDATE: another method is to hack mono_class_inflate_generic_type using copy of internal structures:
struct _MonoGenericInst {
uint32_t id; /* unique ID for debugging */
uint32_t type_argc : 22; /* number of type arguments */
uint32_t is_open : 1; /* if this is an open type */
MonoType *type_argv [1];
};
struct _MonoGenericContext {
/* The instantiation corresponding to the class generic parameters */
MonoGenericInst *class_inst;
/* The instantiation corresponding to the method generic parameters */
void *method_inst;
};
_MonoGenericInst clsctx;
clsctx.type_argc = 1;
clsctx.is_open = 0;
clsctx.type_argv[0] = mono_class_get_type(System::String::_SClass());
MonoGenericContext ctx;
ctx.method_inst = 0;
ctx.class_inst = &clsctx;
MonoType* lt = mono_class_inflate_generic_type(
mono_class_get_type(System::Collections::Generic::List<System::String>::_SClass()),
&ctx);
This doesn't require static link to .a but is even a worse hack. And mono_class_inflate_generic_type is marked as DEPRECATED - so, if this is deprecated, then which is the modern one?
In many cases a mono embedding conundrum can be resolved by using a managed helper method. This is the approach used here.
So we have:
A managed helper method that accepts a generic type definition and an array of generic parameter types.
A client method that accepts a generic type definition name (e.g.: System.Collections.Generic.List`1), an assembly image that contains the type (or use an Assembly Qualified name) and an object of the required generic parameter type. We retrieve the underlying monoType for the object.
Note that when passing type info into the managed layer it has to be an instance of MonoReflectionType as obtained from mono_type_get_object().
The managed helper method is trivial and does the actual instantiation:
public static object CreateInstanceOfGenericType(Type genericTypeDefinition, Type[] parms)
{
// construct type from definition
Type constructedType = genericTypeDefinition.MakeGenericType(parms);
// create instance of constructed type
object obj = Activator.CreateInstance(constructedType);
return obj;
}
The helper code is called, in this case, from Objective-C:
+ (id)createInstanceOfGenericTypeDefinition:(char *)genericTypeDefinitionName monoImage:(MonoImage *)monoImage itemObject:(id)itemObject
{
// get the contained item monoType
MonoType *monoType = [DBType monoTypeForMonoObject:[itemObject monoObject]];
MonoReflectionType *monoReflectionType = mono_type_get_object([DBManagedEnvironment currentDomain], monoType);
// build a System.Array of item types
DBManagedObject *argType = [[DBManagedObject alloc] initWithMonoObject:(MonoObject *)monoReflectionType];
NSArray *argTypes = #[argType];
DBSystem_Array *dbsAargTypes = [argTypes dbsArrayWithTypeName:#"System.Type"];
// get the generic type definition
//
// Retrieves a MonoType from given name. If the name is not fully qualified,
// it defaults to get the type from the image or, if image is NULL or loading
// from it fails, uses corlib.
// This is the embedded equivalent of System.Type.GetType();
MonoType *monoGenericTypeDefinition = mono_reflection_type_from_name(genericTypeDefinitionName, monoImage);
// create instance using helper method
MonoMethod *helperMethod = [DBManagedEnvironment dubrovnikMonoMethodWithName:"CreateInstanceOfGenericType" className:"Dubrovnik.FrameworkHelper.GenericHelper" argCount:2];
void *hargs [2];
hargs[0] = mono_type_get_object([DBManagedEnvironment currentDomain], monoGenericTypeDefinition);
hargs[1] = [dbsAargTypes monoArray]; // a monoArray *
MonoObject *monoException = NULL;
MonoObject *monoObject = mono_runtime_invoke(helperMethod, NULL, hargs, &monoException);
if (monoException) NSRaiseExceptionFromMonoException(monoException);
id object = [System_Object subclassObjectWithMonoObject:monoObject];
return object;
}
For the complete code see Dubrovnik on Github

Symbian: kern-exec 3 panic on RLibrary::Load

I have troubles with dynamic loading of libraries - my code panics with Kern-Exec 3. The code is as follows:
TFileName dllName = _L("mydll.dll");
TFileName dllPath = _L("c:\\sys\\bin\\");
RLibrary dll;
TInt res = dll.Load(dllName, dllPath); // Kern-Exec 3!
TLibraryFunction f = dll.Lookup(1);
if (f)
f();
I receive panic on TInt res = dll.Load(dllName, dllPath); What can I do to get rid of this panic? mydll.dll is really my dll, which has only 1 exported function (for test purposes). Maybe something wrong with the DLL? Here's what it is:
def file:
EXPORTS
_ZN4Init4InitEv # 1 NONAME
pkg file:
#{"mydll DLL"},(0xED3F400D),1,0,0
;Localised Vendor name
%{"Vendor-EN"}
;Unique Vendor name
:"Vendor"
"$(EPOCROOT)Epoc32\release\$(PLATFORM)\$(TARGET)\mydll.dll"-"!:\sys\bin\mydll.dll"
mmp file:
TARGET mydll.dll
TARGETTYPE dll
UID 0x1000008d 0xED3F400D
USERINCLUDE ..\inc
SYSTEMINCLUDE \epoc32\include
SOURCEPATH ..\src
SOURCE mydllDllMain.cpp
LIBRARY euser.lib
#ifdef ENABLE_ABIV2_MODE
DEBUGGABLE_UDEBONLY
#endif
EPOCALLOWDLLDATA
CAPABILITY CommDD LocalServices Location MultimediaDD NetworkControl NetworkServices PowerMgmt ProtServ ReadDeviceData ReadUserData SurroundingsDD SwEvent TrustedUI UserEnvironment WriteDeviceData WriteUserData
source code:
// Exported Functions
namespace Init
{
EXPORT_C TInt Init()
{
// no implementation required
return 0;
}
}
header file:
#ifndef __MYDLL_H__
#define __MYDLL_H__
// Include Files
namespace Init
{
IMPORT_C TInt Init();
}
#endif // __MYDLL_H__
I have no ideas about this... Any help is greatly appreciated.
P.S. I'm trying to do RLibrary::Load because I have troubles with static linkage. When I do static linkage, my main program doesn't start at all. I decided to check what happens and discovered this issue with RLibrary::Load.
A KERN-EXEC 3 panic is caused by an unhandled exception (CPU fault) generated by trying to invalidly access a region of memory. This invalid memory access can be for both code (for example, bad PC by stack corruption) or data (for example, accessing freed memory). As such these are typically observed when dereferencing a NULL pointer (it is equivalent to a segfault).
Certainly the call to RLibrary::Load should never raise a KERN-EXEC 3 due to programmatic error, it is likely to be an environmental issue. As such I have to speculate on what is happening.
I believe the issue that is observed is due to stack overflow. Your MMP file does not specify the stack or heap size the initial thread should use. As such the default of 4Kb (if I remember correctly) will be used. Equally you are using TFileName - use of these on the stack is generally not recommended to avoid... stack overflow.
You would be better off using the _LIT() macro instead - this will allow you to provide the RLibrary::Load function with a descriptor directly referencing the constant strings as located in the constant data section of the binary.
As a side note, you should check the error value to determine the success of the function call.
_LIT(KMyDllName, "mydll.dll");
_LIT(KMyDllPath, "c:\\sys\\bin\\");
RLibrary dll;
TInt res = dll.Load(KMyDllName, MyDllPath); // Hopefully no Kern-Exec 3!
if(err == KErrNone)
{
TLibraryFunction f = dll.Lookup(1);
if (f)
f();
}
// else handle error
The case that you can't use static linkage should be a strong warning to you. It shows that there is something wrong with your DLL and using dynamic linking won't change anything.
Usually in these cases the problem is in mismatched capabilities. DLL must have at least the same set of capabilities that your main program has. And all those capabilities should be covered by your developer cert.