Add .get() method to ResultValue

This commit is contained in:
Olivier FAURE 2018-07-04 15:40:10 +02:00
parent eaf0fda6de
commit d116cedae4
2 changed files with 36 additions and 15 deletions

View File

@ -202,7 +202,7 @@ vk::MemoryDedicatedRequirementsKHR &dedMemReqs = result.get<vk::MemoryDedicatedR
### Return values, Error Codes & Exceptions ### Return values, Error Codes & Exceptions
By default Vulkan-Hpp has exceptions enabled. This means that Vulkan-Hpp checks the return code of each function call which returns a Vk::Result. If Vk::Result is a failure a std::runtime_error will be thrown. Since there is no need to return the error code anymore the C++ bindings can now return the actual desired return value, i.e. a vulkan handle. In those cases ResultValue <SomeType>::type is defined as the returned type. By default Vulkan-Hpp has exceptions enabled. This means that Vulkan-Hpp checks the return code of each function call which returns a Vk::Result. If Vk::Result is a failure a std::runtime_error will be thrown. Since there is no need to return the error code anymore the C++ bindings can now return the actual desired return value, i.e. a vulkan handle. In those cases `ResultValueType<SomeType>::type` is defined as the returned type.
To create a device you can now just write: To create a device you can now just write:
@ -210,11 +210,24 @@ To create a device you can now just write:
vk::Device device = physicalDevice.createDevice(createInfo); vk::Device device = physicalDevice.createDevice(createInfo);
``` ```
If exception handling is disabled by defining `VULKAN_HPP_NO_EXCEPTIONS` the type of `ResultValue<SomeType>::type` is a struct holding a `vk::Result` and a `SomeType`. This struct supports unpacking the return values by using `std::tie`. If exception handling is disabled by defining `VULKAN_HPP_NO_EXCEPTIONS` the type of `ResultValueType<SomeType>::type` is `ResultValue<SomeType>`, a struct holding a `vk::Result` and a `SomeType`. This struct supports unpacking the return values by using `std::tie`, and a `.get()` method that emulates the exceptions-enabled API.
In case you dont want to use the `vk::ArrayProxy` and return value transformation you can still call the plain C-style function. Below are three examples showing the 3 ways to use the API: In case you dont want to use the `vk::ArrayProxy` and return value transformation you can still call the plain C-style function. Below are four examples showing the 4 ways to use the API:
The first snippet shows how to use the API without exceptions and the return value transformation: This first snippet shows how to use the API with exceptions and return value transformation. This is the default mode of the API.
```c++
ShaderModule shader1;
ShaderModule shader2;
try {
myHandle = device.createShaderModule({...});
myHandle2 = device.createShaderModule({...});
} catch(std::exception const &e) {
// handle error and free resources
}
```
This snippet shows how to use the API without exceptions and the return value transformation:
```c++ ```c++
// No exceptions, no return value transformation // No exceptions, no return value transformation
@ -238,7 +251,7 @@ if (result != VK_SUCCESS)
} }
``` ```
The second snippet shows how to use the API using return value transformation, but without exceptions. Its already a little bit shorter than the original code: This snippet shows how to use the API using return value transformation, but without exceptions. Its already a little bit shorter than previous original code:
```c++ ```c++
ResultValue<ShaderModule> shaderResult1 = device.createShaderModule({...} /* createInfo temporary */); ResultValue<ShaderModule> shaderResult1 = device.createShaderModule({...} /* createInfo temporary */);
@ -267,14 +280,14 @@ A nicer way to unpack the result is provided by the structured bindings of C++17
auto [result, shaderModule2] = device.createShaderModule({...} /* createInfo temporary */); auto [result, shaderModule2] = device.createShaderModule({...} /* createInfo temporary */);
``` ```
Finally, the last code example is using exceptions and return value transformation. This is the default mode of the API. Finally, the last code example uses return value transformation, has exceptions disabled, and uses the `.get()` method. This is similar to the default API.
```c++ ```c++
ShaderModule shader1; ShaderModule shader1;
ShaderModule shader2; ShaderModule shader2;
try { try {
myHandle = device.createShaderModule({...}); myHandle = device.createShaderModule({...}).get();
myHandle2 = device.createShaderModule({...}); myHandle2 = device.createShaderModule({...}).get();
} catch(std::exception const &e) { } catch(std::exception const &e) {
// handle error and free resources // handle error and free resources
} }
@ -353,7 +366,7 @@ device.getQueue(graphics_queue_family_index, 0, &graphics_queue, dldid);
Feel free to submit a PR to add to this list. Feel free to submit a PR to add to this list.
- [Examples](https://github.com/jherico/vulkan) A port of Sascha Willems [examples](https://github.com/SaschaWillems/Vulkan) to Vulkan-Hpp - [Examples](https://github.com/jherico/vulkan) A port of Sascha Willems [examples](https://github.com/SaschaWillems/Vulkan) to Vulkan-Hpp
- [Vookoo](https://github.com/andy-thomason/Vookoo/) Stateful helper classes for Vulkan-Hpp, [Introduction Article](https://accu.org/index.php/journals/2380). - [Vookoo](https://github.com/andy-thomason/Vookoo/) Stateful helper classes for Vulkan-Hpp, [Introduction Article](https://accu.org/index.php/journals/2380).
## License ## License
@ -371,4 +384,3 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.

View File

@ -390,7 +390,7 @@ const std::string structureChainHeader = R"(
public: public:
StructureChain() StructureChain()
{ {
link<StructureElements...>(); link<StructureElements...>();
} }
StructureChain(StructureChain const &rhs) StructureChain(StructureChain const &rhs)
@ -527,6 +527,15 @@ const std::string resultValueHeader = R"(
T value; T value;
operator std::tuple<Result&, T&>() { return std::tuple<Result&, T&>(result, value); } operator std::tuple<Result&, T&>() { return std::tuple<Result&, T&>(result, value); }
VULKAN_HPP_INLINE T get()
{
if ( result != Result::eSuccess )
{
throwResultException( result, VULKAN_HPP_NAMESPACE_STRING "::ResultValue::get" );
}
return value;
}
}; };
template <typename T> template <typename T>
@ -691,7 +700,7 @@ const std::string uniqueHandleHeader = R"(
{ {
return m_value; return m_value;
} }
Type & get() Type & get()
{ {
return m_value; return m_value;
@ -4477,7 +4486,7 @@ void VulkanHppGenerator::writeTypeHandle(std::ostream & os, DependencyData const
${className} & operator=(Vk${className} ${memberName}) ${className} & operator=(Vk${className} ${memberName})
{ {
m_${memberName} = ${memberName}; m_${memberName} = ${memberName};
return *this; return *this;
} }
#endif #endif
@ -5016,11 +5025,11 @@ void VulkanHppGenerator::writeDelegationClassDynamic(std::ostream &os)
for (auto command : m_commands) for (auto command : m_commands)
{ {
enterProtect(os, command.second.protect); enterProtect(os, command.second.protect);
if (!command.second.params.empty() if (!command.second.params.empty()
&& m_handles.find(command.second.params[0].type) != m_handles.end() && m_handles.find(command.second.params[0].type) != m_handles.end()
&& command.second.params[0].type != "Instance") && command.second.params[0].type != "Instance")
{ {
os << " vk" << startUpperCase(command.second.fullName) << " = PFN_vk" << startUpperCase(command.second.fullName) os << " vk" << startUpperCase(command.second.fullName) << " = PFN_vk" << startUpperCase(command.second.fullName)
<< "(device ? device.getProcAddr( \"vk" << startUpperCase(command.second.fullName) << "\") : instance.getProcAddr( \"vk" << startUpperCase(command.second.fullName) << "\"));" << std::endl; << "(device ? device.getProcAddr( \"vk" << startUpperCase(command.second.fullName) << "\") : instance.getProcAddr( \"vk" << startUpperCase(command.second.fullName) << "\"));" << std::endl;
} }
else { else {