realitix / vulkan

The ultimate Python binding for Vulkan API
Apache License 2.0
505 stars 46 forks source link

extensions functions call bugs #54

Closed mackst closed 5 years ago

mackst commented 5 years ago

vkGetPhysicalDeviceFeatures2 call is missing sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2

def _wrap_vkGetPhysicalDeviceFeatures2(fn):
    def vkGetPhysicalDeviceFeatures2(physicalDevice
            ,):

        pFeatures = ffi.new('VkPhysicalDeviceFeatures2*')
        #pFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2

        result = _callApi(fn, physicalDevice,pFeatures)

        return pFeatures[0]

Here is another C\C++ usage code which not able to do

    VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptorIndexing = { };
    descriptorIndexing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;

    VkPhysicalDeviceFeatures2 features2 = { };
    features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;

    auto found = std::find(_deviceExtensions.begin(), _deviceExtensions.end(), VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
    if (found != _deviceExtensions.end())
        features2.pNext = &descriptorIndexing;

    vkGetPhysicalDeviceFeatures2( _physicalDevice, &features2 );

vkGetPhysicalDeviceProperties2 is the same not able to assign other structs to pNext

def _wrap_vkGetPhysicalDeviceProperties2(fn):
    def vkGetPhysicalDeviceProperties2(physicalDevice
            ,pNext=ffi.NULL):

        pProperties = ffi.new('VkPhysicalDeviceProperties2*')
        #pProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
        #if pNext != ffi.NULL:
            #pProperties.pNext = ffi.addressof(pNext)

        result = _callApi(fn, physicalDevice,pProperties)

        return pProperties[0]

    return vkGetPhysicalDeviceProperties2

Example of usage

# VkPhysicalDeviceRayTracingPropertiesNV should be able to pass to VkPhysicalDeviceProperties2.pNext
self._rayTracingProperties = VkPhysicalDeviceRayTracingPropertiesNV(
            maxRecursionDepth=0,
            shaderGroupHandleSize=0
        )
props = vkGetPhysicalDeviceProperties2KHR(self._physicalDevice, self._rayTracingProperties)

I'm working on the VKRay examples and found out above issues. There could be more bugs. Right now I change the code(comment out on above) to pass those bugs.

mackst commented 5 years ago
def _wrap_vkGetAccelerationStructureHandleNV(fn):
    def vkGetAccelerationStructureHandleNV(device
            ,accelerationStructure
            ,dataSize
            ,):

        pData = ffi.new('void*')

        result = _callApi(fn, device,accelerationStructure,dataSize,pData)
        if result != VK_SUCCESS:
            raise exception_codes[result]

        return pData[0]

pData = ffi.new('void*') should be pData = ffi.new('uint64_t*')

realitix commented 5 years ago

Hello,

Thanks for the report, I will take a look.

mackst commented 5 years ago

Hi realitix,

Found another one

def _wrap_vkGetRayTracingShaderGroupHandlesNV(fn):
    def vkGetRayTracingShaderGroupHandlesNV(device
            ,pipeline
            ,firstGroup
            ,groupCount
            ,dataSize
            ,data=ffi.NULL):

        pData = ffi.new('void*')
        #pData = ffi.new('uint64_t*')
        #if data:
            #pData = data

        result = _callApi(fn, device,pipeline,firstGroup,groupCount,dataSize,pData)
        if result != VK_SUCCESS:
            raise exception_codes[result]

        return pData[0]

This one maybe a bit more tricky. The C++ example of usage

// _shaderBindingTable is a buffer class to create buffer
VkResult code = _shaderBindingTable.Create(shaderBindingTableSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
// call vkMapMemory to get the buffer memory
void* mappedMemory = _shaderBindingTable.Map(shaderBindingTableSize);
// vkGetRayTracingShaderGroupHandlesNV fill the real Ray Tracing Shader Group Handles data to mappedMemory
code = vkGetRayTracingShaderGroupHandlesNV(_device, _rtPipeline, 0, groupNum, shaderBindingTableSize, mappedMemory);

_shaderBindingTable.Unmap();

First pData = ffi.new('void*') is all ways failed to run. Change to pData = ffi.new('uint64_t*') works but in the RTX pipeline we need this data to fill into the buffer. And vkMapMemory return a ffi.buffer obj which I don't know howto fill the return data to it. Here is the working change for me.

in _vulkan.py

def _wrap_vkGetRayTracingShaderGroupHandlesNV(fn):
    def vkGetRayTracingShaderGroupHandlesNV(device
            ,pipeline
            ,firstGroup
            ,groupCount
            ,dataSize
            ,data=ffi.NULL):

        pData = ffi.new('uint64_t*')
        if data:
            pData = data

        result = _callApi(fn, device,pipeline,firstGroup,groupCount,dataSize,pData)
        if result != VK_SUCCESS:
            raise exception_codes[result]

        return pData[0]

In the app side

self._shaderBindingTable.create(shaderBindingTableSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)

mappedMemory = self._shaderBindingTable.map(shaderBindingTableSize)
# get the cdata back from the buffer obj
buf = ffi.from_buffer(mappedMemory, require_writable=True)
# pass it to the call
rtsgHandles = vkGetRayTracingShaderGroupHandlesNV(self._device, self._rtPipeline, 0, groupNum, shaderBindingTableSize, buf)

self._shaderBindingTable.unmap()
mackst commented 5 years ago

VK_SHADER_UNUSED_NV should not be None debug with C++ got this VK_SHADER_UNUSED_NV = 4294967295

mackst commented 5 years ago

here is the example code you can try https://github.com/mackst/pyVkRayTutorials

realitix commented 5 years ago

I'm working on it. Extension functions are not well managed...

realitix commented 5 years ago

I fixed the first problem, you can now override the return value in extension functions (so you can set stype and pnext manually). I'm working on the others problems.

realitix commented 5 years ago

Ok I fixed everything, can you try with the master version.

mackst commented 5 years ago

Thanks fix it. I tied. There still small issues. Take vkGetPhysicalDeviceProperties2 for example

self._rayTracingProperties = VkPhysicalDeviceRayTracingPropertiesNV(
            maxRecursionDepth=0,
            shaderGroupHandleSize=0
        )
properties2 = VkPhysicalDeviceProperties2(pNext=self._rayTracingProperties)
props = vkGetPhysicalDeviceProperties2KHR(self._physicalDevice, properties2)

Will get error

Traceback (most recent call last):
  File "D:/codeWorkspace/vulkan/pyVkRayTutorials/01_InitRaytracing.py", line 135, in <module>
    win.run()
  File "D:\codeWorkspace\vulkan\pyVkRayTutorials\application.py", line 471, in run
    self.initialize()
  File "D:\codeWorkspace\vulkan\pyVkRayTutorials\application.py", line 491, in initialize
    self.init()
  File "D:/codeWorkspace/vulkan/pyVkRayTutorials/01_InitRaytracing.py", line 125, in init
    props = vkGetPhysicalDeviceProperties2KHR(self._physicalDevice, properties2)
  File "D:\codeWorkspace\vulkan\pyVkRayTutorials\application.py", line 22, in __call__
    return func(*args, **kwargs)
  File "D:\codeWorkspace\venv\vulkan37\lib\site-packages\vulkan\_vulkan.py", line 7446, in vkGetPhysicalDeviceProperties2
    return pProperties[0]
TypeError: cdata of type 'struct VkPhysicalDeviceProperties2' cannot be indexed

If pProperties is given should just return it.

realitix commented 5 years ago

Hello @mackst, I pushed a commit to fix it. Can you try again ?

mackst commented 5 years ago

Cool. All works.

realitix commented 5 years ago

great