How do I know if I'm abstracting graphics APIs too tightly?
up vote
21
down vote
favorite
When making a renderer that supports multiple graphics APIs, you would typically want to abstract your code in some sort of low level library that is tied with some graphics API like OpenGL, Vulkan, D3D11 and so on;
They work very differently from each other, so making a good generic API becomes essential;
I've read that you would typically want to use a "back-end" that implements the basic functionality for each API you want to support, and a "front-end" which is what is used by the programmer to draw stuff on the screen.
How do I know if I'm making too much of a tight abstraction?
graphics-programming
add a comment |
up vote
21
down vote
favorite
When making a renderer that supports multiple graphics APIs, you would typically want to abstract your code in some sort of low level library that is tied with some graphics API like OpenGL, Vulkan, D3D11 and so on;
They work very differently from each other, so making a good generic API becomes essential;
I've read that you would typically want to use a "back-end" that implements the basic functionality for each API you want to support, and a "front-end" which is what is used by the programmer to draw stuff on the screen.
How do I know if I'm making too much of a tight abstraction?
graphics-programming
5
Are you 100% certain that your wrapper + Vulkan or D3D11 is faster than just always using OpenGL?
– Mooing Duck
Nov 30 at 22:58
@Mooing Duck if used correctly, yes.
– Gabriele Vierti
Dec 1 at 7:34
3
I would seriously doubt that. Most of the gains in Vulkan come from being very low-level and doing things in a very peculiar, specific way. Something that is generic enough to also do the same seamlessly in OpenGL or D3D almost certainly can't do that. Reimplementing the same stuff as OpenGL does (like many Vulkan tutorials do, ironically) results in 99.99% the same performance, with 20 times the work.
– Damon
Dec 1 at 15:46
@Damon that's right, but newer APIs are specifically designed (and not adapted like OpenGL) to work on modern gpus; speaking of Vulkan, you can pretty much use the same API on every supported platform, contrarily to OpenGL, where you need to use the "Embedded Systems" version. Other than less cpu overhead and fancy features we don't have much, but in the future we might have some pretty surprising techniques that may run faster using Vk or D3D12 rather than OGL or D3D11
– Gabriele Vierti
Dec 1 at 16:04
add a comment |
up vote
21
down vote
favorite
up vote
21
down vote
favorite
When making a renderer that supports multiple graphics APIs, you would typically want to abstract your code in some sort of low level library that is tied with some graphics API like OpenGL, Vulkan, D3D11 and so on;
They work very differently from each other, so making a good generic API becomes essential;
I've read that you would typically want to use a "back-end" that implements the basic functionality for each API you want to support, and a "front-end" which is what is used by the programmer to draw stuff on the screen.
How do I know if I'm making too much of a tight abstraction?
graphics-programming
When making a renderer that supports multiple graphics APIs, you would typically want to abstract your code in some sort of low level library that is tied with some graphics API like OpenGL, Vulkan, D3D11 and so on;
They work very differently from each other, so making a good generic API becomes essential;
I've read that you would typically want to use a "back-end" that implements the basic functionality for each API you want to support, and a "front-end" which is what is used by the programmer to draw stuff on the screen.
How do I know if I'm making too much of a tight abstraction?
graphics-programming
graphics-programming
edited Dec 1 at 8:37
asked Nov 30 at 8:06
Gabriele Vierti
350214
350214
5
Are you 100% certain that your wrapper + Vulkan or D3D11 is faster than just always using OpenGL?
– Mooing Duck
Nov 30 at 22:58
@Mooing Duck if used correctly, yes.
– Gabriele Vierti
Dec 1 at 7:34
3
I would seriously doubt that. Most of the gains in Vulkan come from being very low-level and doing things in a very peculiar, specific way. Something that is generic enough to also do the same seamlessly in OpenGL or D3D almost certainly can't do that. Reimplementing the same stuff as OpenGL does (like many Vulkan tutorials do, ironically) results in 99.99% the same performance, with 20 times the work.
– Damon
Dec 1 at 15:46
@Damon that's right, but newer APIs are specifically designed (and not adapted like OpenGL) to work on modern gpus; speaking of Vulkan, you can pretty much use the same API on every supported platform, contrarily to OpenGL, where you need to use the "Embedded Systems" version. Other than less cpu overhead and fancy features we don't have much, but in the future we might have some pretty surprising techniques that may run faster using Vk or D3D12 rather than OGL or D3D11
– Gabriele Vierti
Dec 1 at 16:04
add a comment |
5
Are you 100% certain that your wrapper + Vulkan or D3D11 is faster than just always using OpenGL?
– Mooing Duck
Nov 30 at 22:58
@Mooing Duck if used correctly, yes.
– Gabriele Vierti
Dec 1 at 7:34
3
I would seriously doubt that. Most of the gains in Vulkan come from being very low-level and doing things in a very peculiar, specific way. Something that is generic enough to also do the same seamlessly in OpenGL or D3D almost certainly can't do that. Reimplementing the same stuff as OpenGL does (like many Vulkan tutorials do, ironically) results in 99.99% the same performance, with 20 times the work.
– Damon
Dec 1 at 15:46
@Damon that's right, but newer APIs are specifically designed (and not adapted like OpenGL) to work on modern gpus; speaking of Vulkan, you can pretty much use the same API on every supported platform, contrarily to OpenGL, where you need to use the "Embedded Systems" version. Other than less cpu overhead and fancy features we don't have much, but in the future we might have some pretty surprising techniques that may run faster using Vk or D3D12 rather than OGL or D3D11
– Gabriele Vierti
Dec 1 at 16:04
5
5
Are you 100% certain that your wrapper + Vulkan or D3D11 is faster than just always using OpenGL?
– Mooing Duck
Nov 30 at 22:58
Are you 100% certain that your wrapper + Vulkan or D3D11 is faster than just always using OpenGL?
– Mooing Duck
Nov 30 at 22:58
@Mooing Duck if used correctly, yes.
– Gabriele Vierti
Dec 1 at 7:34
@Mooing Duck if used correctly, yes.
– Gabriele Vierti
Dec 1 at 7:34
3
3
I would seriously doubt that. Most of the gains in Vulkan come from being very low-level and doing things in a very peculiar, specific way. Something that is generic enough to also do the same seamlessly in OpenGL or D3D almost certainly can't do that. Reimplementing the same stuff as OpenGL does (like many Vulkan tutorials do, ironically) results in 99.99% the same performance, with 20 times the work.
– Damon
Dec 1 at 15:46
I would seriously doubt that. Most of the gains in Vulkan come from being very low-level and doing things in a very peculiar, specific way. Something that is generic enough to also do the same seamlessly in OpenGL or D3D almost certainly can't do that. Reimplementing the same stuff as OpenGL does (like many Vulkan tutorials do, ironically) results in 99.99% the same performance, with 20 times the work.
– Damon
Dec 1 at 15:46
@Damon that's right, but newer APIs are specifically designed (and not adapted like OpenGL) to work on modern gpus; speaking of Vulkan, you can pretty much use the same API on every supported platform, contrarily to OpenGL, where you need to use the "Embedded Systems" version. Other than less cpu overhead and fancy features we don't have much, but in the future we might have some pretty surprising techniques that may run faster using Vk or D3D12 rather than OGL or D3D11
– Gabriele Vierti
Dec 1 at 16:04
@Damon that's right, but newer APIs are specifically designed (and not adapted like OpenGL) to work on modern gpus; speaking of Vulkan, you can pretty much use the same API on every supported platform, contrarily to OpenGL, where you need to use the "Embedded Systems" version. Other than less cpu overhead and fancy features we don't have much, but in the future we might have some pretty surprising techniques that may run faster using Vk or D3D12 rather than OGL or D3D11
– Gabriele Vierti
Dec 1 at 16:04
add a comment |
3 Answers
3
active
oldest
votes
up vote
42
down vote
accepted
First of all, consider if it is actually worth it to support more than one graphics API. Just using OpenGL will cover most platforms and will be "good enough" for all but the most graphically ambitious projects. Unless you work for a very large game studio which can afford to sink several thousand person-hours into implementing and testing multiple rendering backends and unless there are some DirectX or Vulcan specific features you really want to show off, it is usually not worth the hassle. Especially considering that you can save a lot of work by using an abstraction layer someone else created (a 3rd party library or game engine).
But let's assume that you already evaluated your options and came to the conclusion that it is both viable and worth the time to roll your own.
Then the main judge of your abstraction layer's software architecture are your front-end programmers.
- Are they able to implement the game systems they want to implement without having to wonder about any low-level details?
- Are they able to completely ignore that there is more than one graphics API?
- Would it theoretically be possible to add yet another rendering backend without changing any of the front-end code?
If so, you succeeded.
2
One additional suggestion: is it worth emphasizing that the goal is to achieve the goals in the bullet points with the minimal level of effort--to just hit the target and go no further? Otherwise each one of these can turn into a rabbit hole for the typical developer who (myself included) often doesn't know when to leave good-enough alone. :) And also that the only reliable way to judge success is to develop and test the API iteratively with actual users; it's impossible to guess accurately, and leads to a rabbit hole scenario of over-engineering.
– bob
Nov 30 at 15:48
5
I would add that, if you really do have to support multiple graphics libraries, there's almost certainly an off-the-shelf one that does everything you need to, so even then you really shouldn't roll your own. (Of course, there are exceptions, but if you're inexperienced enough to ask "how tight of an abstraction should I make" you're probably not working on a project that requires you to do it)
– Nic Hartley
Nov 30 at 19:27
I'm not a graphics dev, but looking at compatibility frameworks from the history of databases and OSes, I'd add that it's almost certainly just not worth it to make your own general framework. The framework will almost certainly have to sacrifice performance for compatibility, which probably means you can't do much with those specialized features anyway. Existing frameworks are nearly certain to handle those issues better due to wider usage. Now, if you have the massive budget you describe and want to build a specialized framework (say for one game or series), that might be more doable.
– jpmc26
Dec 2 at 21:18
add a comment |
up vote
5
down vote
Start by identifying what you actually need out of the "wrapper" part of the API. It's generally very, very simple: you need the basic resources (buffers, shaders, textures, pipeline state) and a way to use those resources to construct a frame by submitting some draw calls.
Try to keep any high-level logic out of the wrapper portion of the API. If you implement a clever scene culling technique in this portion of the API, well now you are on the hook to duplicate that logic in all of the backend implementations. That's a lot of extra effort, so keep it simple. Scene management should be part of a higher-level portion of the API that uses the wrapper rather than being part of the wrapper itself.
Choose the targets you will support and understand them. It's hard to write decent wrappers for "everything," and you probably don't need to (arguably you don't need to write a single wrapper, either, as noted in Philipp's answer). It's almost impossible to write a decent wrapper if you don't know the APIs you're going to wrap already.
Evaluate the state of your API regularly. It should in general have a smaller surface area than the underlying wrapped APIs; if you find yourself creating one-to-one wrapper types for every D3D structure or every OpenGL function call you are probably veering off course.
Look at what work has gone before. Sokol and BGFX are APIs that provide levels of agnosticism that may be useful to you, and are relatively easy to understand (the former especially).
add a comment |
up vote
2
down vote
Another point not yet mentioned which you should consider is what your performance goals are. If your goal is to have a graphics library that will yield good performance out of a cheap hardware platform, but also be usable on a variety of platforms that are vastly more powerful but use a different API, it may make sense to design your API around whatever abstractions are used natively on the platform where performance is an issue. Even if this causes a 50% speed degradation on the more powerful platforms, it may be worth it if it allows a 20% speed improvement on the platform where performance matters most.
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
42
down vote
accepted
First of all, consider if it is actually worth it to support more than one graphics API. Just using OpenGL will cover most platforms and will be "good enough" for all but the most graphically ambitious projects. Unless you work for a very large game studio which can afford to sink several thousand person-hours into implementing and testing multiple rendering backends and unless there are some DirectX or Vulcan specific features you really want to show off, it is usually not worth the hassle. Especially considering that you can save a lot of work by using an abstraction layer someone else created (a 3rd party library or game engine).
But let's assume that you already evaluated your options and came to the conclusion that it is both viable and worth the time to roll your own.
Then the main judge of your abstraction layer's software architecture are your front-end programmers.
- Are they able to implement the game systems they want to implement without having to wonder about any low-level details?
- Are they able to completely ignore that there is more than one graphics API?
- Would it theoretically be possible to add yet another rendering backend without changing any of the front-end code?
If so, you succeeded.
2
One additional suggestion: is it worth emphasizing that the goal is to achieve the goals in the bullet points with the minimal level of effort--to just hit the target and go no further? Otherwise each one of these can turn into a rabbit hole for the typical developer who (myself included) often doesn't know when to leave good-enough alone. :) And also that the only reliable way to judge success is to develop and test the API iteratively with actual users; it's impossible to guess accurately, and leads to a rabbit hole scenario of over-engineering.
– bob
Nov 30 at 15:48
5
I would add that, if you really do have to support multiple graphics libraries, there's almost certainly an off-the-shelf one that does everything you need to, so even then you really shouldn't roll your own. (Of course, there are exceptions, but if you're inexperienced enough to ask "how tight of an abstraction should I make" you're probably not working on a project that requires you to do it)
– Nic Hartley
Nov 30 at 19:27
I'm not a graphics dev, but looking at compatibility frameworks from the history of databases and OSes, I'd add that it's almost certainly just not worth it to make your own general framework. The framework will almost certainly have to sacrifice performance for compatibility, which probably means you can't do much with those specialized features anyway. Existing frameworks are nearly certain to handle those issues better due to wider usage. Now, if you have the massive budget you describe and want to build a specialized framework (say for one game or series), that might be more doable.
– jpmc26
Dec 2 at 21:18
add a comment |
up vote
42
down vote
accepted
First of all, consider if it is actually worth it to support more than one graphics API. Just using OpenGL will cover most platforms and will be "good enough" for all but the most graphically ambitious projects. Unless you work for a very large game studio which can afford to sink several thousand person-hours into implementing and testing multiple rendering backends and unless there are some DirectX or Vulcan specific features you really want to show off, it is usually not worth the hassle. Especially considering that you can save a lot of work by using an abstraction layer someone else created (a 3rd party library or game engine).
But let's assume that you already evaluated your options and came to the conclusion that it is both viable and worth the time to roll your own.
Then the main judge of your abstraction layer's software architecture are your front-end programmers.
- Are they able to implement the game systems they want to implement without having to wonder about any low-level details?
- Are they able to completely ignore that there is more than one graphics API?
- Would it theoretically be possible to add yet another rendering backend without changing any of the front-end code?
If so, you succeeded.
2
One additional suggestion: is it worth emphasizing that the goal is to achieve the goals in the bullet points with the minimal level of effort--to just hit the target and go no further? Otherwise each one of these can turn into a rabbit hole for the typical developer who (myself included) often doesn't know when to leave good-enough alone. :) And also that the only reliable way to judge success is to develop and test the API iteratively with actual users; it's impossible to guess accurately, and leads to a rabbit hole scenario of over-engineering.
– bob
Nov 30 at 15:48
5
I would add that, if you really do have to support multiple graphics libraries, there's almost certainly an off-the-shelf one that does everything you need to, so even then you really shouldn't roll your own. (Of course, there are exceptions, but if you're inexperienced enough to ask "how tight of an abstraction should I make" you're probably not working on a project that requires you to do it)
– Nic Hartley
Nov 30 at 19:27
I'm not a graphics dev, but looking at compatibility frameworks from the history of databases and OSes, I'd add that it's almost certainly just not worth it to make your own general framework. The framework will almost certainly have to sacrifice performance for compatibility, which probably means you can't do much with those specialized features anyway. Existing frameworks are nearly certain to handle those issues better due to wider usage. Now, if you have the massive budget you describe and want to build a specialized framework (say for one game or series), that might be more doable.
– jpmc26
Dec 2 at 21:18
add a comment |
up vote
42
down vote
accepted
up vote
42
down vote
accepted
First of all, consider if it is actually worth it to support more than one graphics API. Just using OpenGL will cover most platforms and will be "good enough" for all but the most graphically ambitious projects. Unless you work for a very large game studio which can afford to sink several thousand person-hours into implementing and testing multiple rendering backends and unless there are some DirectX or Vulcan specific features you really want to show off, it is usually not worth the hassle. Especially considering that you can save a lot of work by using an abstraction layer someone else created (a 3rd party library or game engine).
But let's assume that you already evaluated your options and came to the conclusion that it is both viable and worth the time to roll your own.
Then the main judge of your abstraction layer's software architecture are your front-end programmers.
- Are they able to implement the game systems they want to implement without having to wonder about any low-level details?
- Are they able to completely ignore that there is more than one graphics API?
- Would it theoretically be possible to add yet another rendering backend without changing any of the front-end code?
If so, you succeeded.
First of all, consider if it is actually worth it to support more than one graphics API. Just using OpenGL will cover most platforms and will be "good enough" for all but the most graphically ambitious projects. Unless you work for a very large game studio which can afford to sink several thousand person-hours into implementing and testing multiple rendering backends and unless there are some DirectX or Vulcan specific features you really want to show off, it is usually not worth the hassle. Especially considering that you can save a lot of work by using an abstraction layer someone else created (a 3rd party library or game engine).
But let's assume that you already evaluated your options and came to the conclusion that it is both viable and worth the time to roll your own.
Then the main judge of your abstraction layer's software architecture are your front-end programmers.
- Are they able to implement the game systems they want to implement without having to wonder about any low-level details?
- Are they able to completely ignore that there is more than one graphics API?
- Would it theoretically be possible to add yet another rendering backend without changing any of the front-end code?
If so, you succeeded.
edited Nov 30 at 11:26
answered Nov 30 at 9:44
Philipp
76.7k19180230
76.7k19180230
2
One additional suggestion: is it worth emphasizing that the goal is to achieve the goals in the bullet points with the minimal level of effort--to just hit the target and go no further? Otherwise each one of these can turn into a rabbit hole for the typical developer who (myself included) often doesn't know when to leave good-enough alone. :) And also that the only reliable way to judge success is to develop and test the API iteratively with actual users; it's impossible to guess accurately, and leads to a rabbit hole scenario of over-engineering.
– bob
Nov 30 at 15:48
5
I would add that, if you really do have to support multiple graphics libraries, there's almost certainly an off-the-shelf one that does everything you need to, so even then you really shouldn't roll your own. (Of course, there are exceptions, but if you're inexperienced enough to ask "how tight of an abstraction should I make" you're probably not working on a project that requires you to do it)
– Nic Hartley
Nov 30 at 19:27
I'm not a graphics dev, but looking at compatibility frameworks from the history of databases and OSes, I'd add that it's almost certainly just not worth it to make your own general framework. The framework will almost certainly have to sacrifice performance for compatibility, which probably means you can't do much with those specialized features anyway. Existing frameworks are nearly certain to handle those issues better due to wider usage. Now, if you have the massive budget you describe and want to build a specialized framework (say for one game or series), that might be more doable.
– jpmc26
Dec 2 at 21:18
add a comment |
2
One additional suggestion: is it worth emphasizing that the goal is to achieve the goals in the bullet points with the minimal level of effort--to just hit the target and go no further? Otherwise each one of these can turn into a rabbit hole for the typical developer who (myself included) often doesn't know when to leave good-enough alone. :) And also that the only reliable way to judge success is to develop and test the API iteratively with actual users; it's impossible to guess accurately, and leads to a rabbit hole scenario of over-engineering.
– bob
Nov 30 at 15:48
5
I would add that, if you really do have to support multiple graphics libraries, there's almost certainly an off-the-shelf one that does everything you need to, so even then you really shouldn't roll your own. (Of course, there are exceptions, but if you're inexperienced enough to ask "how tight of an abstraction should I make" you're probably not working on a project that requires you to do it)
– Nic Hartley
Nov 30 at 19:27
I'm not a graphics dev, but looking at compatibility frameworks from the history of databases and OSes, I'd add that it's almost certainly just not worth it to make your own general framework. The framework will almost certainly have to sacrifice performance for compatibility, which probably means you can't do much with those specialized features anyway. Existing frameworks are nearly certain to handle those issues better due to wider usage. Now, if you have the massive budget you describe and want to build a specialized framework (say for one game or series), that might be more doable.
– jpmc26
Dec 2 at 21:18
2
2
One additional suggestion: is it worth emphasizing that the goal is to achieve the goals in the bullet points with the minimal level of effort--to just hit the target and go no further? Otherwise each one of these can turn into a rabbit hole for the typical developer who (myself included) often doesn't know when to leave good-enough alone. :) And also that the only reliable way to judge success is to develop and test the API iteratively with actual users; it's impossible to guess accurately, and leads to a rabbit hole scenario of over-engineering.
– bob
Nov 30 at 15:48
One additional suggestion: is it worth emphasizing that the goal is to achieve the goals in the bullet points with the minimal level of effort--to just hit the target and go no further? Otherwise each one of these can turn into a rabbit hole for the typical developer who (myself included) often doesn't know when to leave good-enough alone. :) And also that the only reliable way to judge success is to develop and test the API iteratively with actual users; it's impossible to guess accurately, and leads to a rabbit hole scenario of over-engineering.
– bob
Nov 30 at 15:48
5
5
I would add that, if you really do have to support multiple graphics libraries, there's almost certainly an off-the-shelf one that does everything you need to, so even then you really shouldn't roll your own. (Of course, there are exceptions, but if you're inexperienced enough to ask "how tight of an abstraction should I make" you're probably not working on a project that requires you to do it)
– Nic Hartley
Nov 30 at 19:27
I would add that, if you really do have to support multiple graphics libraries, there's almost certainly an off-the-shelf one that does everything you need to, so even then you really shouldn't roll your own. (Of course, there are exceptions, but if you're inexperienced enough to ask "how tight of an abstraction should I make" you're probably not working on a project that requires you to do it)
– Nic Hartley
Nov 30 at 19:27
I'm not a graphics dev, but looking at compatibility frameworks from the history of databases and OSes, I'd add that it's almost certainly just not worth it to make your own general framework. The framework will almost certainly have to sacrifice performance for compatibility, which probably means you can't do much with those specialized features anyway. Existing frameworks are nearly certain to handle those issues better due to wider usage. Now, if you have the massive budget you describe and want to build a specialized framework (say for one game or series), that might be more doable.
– jpmc26
Dec 2 at 21:18
I'm not a graphics dev, but looking at compatibility frameworks from the history of databases and OSes, I'd add that it's almost certainly just not worth it to make your own general framework. The framework will almost certainly have to sacrifice performance for compatibility, which probably means you can't do much with those specialized features anyway. Existing frameworks are nearly certain to handle those issues better due to wider usage. Now, if you have the massive budget you describe and want to build a specialized framework (say for one game or series), that might be more doable.
– jpmc26
Dec 2 at 21:18
add a comment |
up vote
5
down vote
Start by identifying what you actually need out of the "wrapper" part of the API. It's generally very, very simple: you need the basic resources (buffers, shaders, textures, pipeline state) and a way to use those resources to construct a frame by submitting some draw calls.
Try to keep any high-level logic out of the wrapper portion of the API. If you implement a clever scene culling technique in this portion of the API, well now you are on the hook to duplicate that logic in all of the backend implementations. That's a lot of extra effort, so keep it simple. Scene management should be part of a higher-level portion of the API that uses the wrapper rather than being part of the wrapper itself.
Choose the targets you will support and understand them. It's hard to write decent wrappers for "everything," and you probably don't need to (arguably you don't need to write a single wrapper, either, as noted in Philipp's answer). It's almost impossible to write a decent wrapper if you don't know the APIs you're going to wrap already.
Evaluate the state of your API regularly. It should in general have a smaller surface area than the underlying wrapped APIs; if you find yourself creating one-to-one wrapper types for every D3D structure or every OpenGL function call you are probably veering off course.
Look at what work has gone before. Sokol and BGFX are APIs that provide levels of agnosticism that may be useful to you, and are relatively easy to understand (the former especially).
add a comment |
up vote
5
down vote
Start by identifying what you actually need out of the "wrapper" part of the API. It's generally very, very simple: you need the basic resources (buffers, shaders, textures, pipeline state) and a way to use those resources to construct a frame by submitting some draw calls.
Try to keep any high-level logic out of the wrapper portion of the API. If you implement a clever scene culling technique in this portion of the API, well now you are on the hook to duplicate that logic in all of the backend implementations. That's a lot of extra effort, so keep it simple. Scene management should be part of a higher-level portion of the API that uses the wrapper rather than being part of the wrapper itself.
Choose the targets you will support and understand them. It's hard to write decent wrappers for "everything," and you probably don't need to (arguably you don't need to write a single wrapper, either, as noted in Philipp's answer). It's almost impossible to write a decent wrapper if you don't know the APIs you're going to wrap already.
Evaluate the state of your API regularly. It should in general have a smaller surface area than the underlying wrapped APIs; if you find yourself creating one-to-one wrapper types for every D3D structure or every OpenGL function call you are probably veering off course.
Look at what work has gone before. Sokol and BGFX are APIs that provide levels of agnosticism that may be useful to you, and are relatively easy to understand (the former especially).
add a comment |
up vote
5
down vote
up vote
5
down vote
Start by identifying what you actually need out of the "wrapper" part of the API. It's generally very, very simple: you need the basic resources (buffers, shaders, textures, pipeline state) and a way to use those resources to construct a frame by submitting some draw calls.
Try to keep any high-level logic out of the wrapper portion of the API. If you implement a clever scene culling technique in this portion of the API, well now you are on the hook to duplicate that logic in all of the backend implementations. That's a lot of extra effort, so keep it simple. Scene management should be part of a higher-level portion of the API that uses the wrapper rather than being part of the wrapper itself.
Choose the targets you will support and understand them. It's hard to write decent wrappers for "everything," and you probably don't need to (arguably you don't need to write a single wrapper, either, as noted in Philipp's answer). It's almost impossible to write a decent wrapper if you don't know the APIs you're going to wrap already.
Evaluate the state of your API regularly. It should in general have a smaller surface area than the underlying wrapped APIs; if you find yourself creating one-to-one wrapper types for every D3D structure or every OpenGL function call you are probably veering off course.
Look at what work has gone before. Sokol and BGFX are APIs that provide levels of agnosticism that may be useful to you, and are relatively easy to understand (the former especially).
Start by identifying what you actually need out of the "wrapper" part of the API. It's generally very, very simple: you need the basic resources (buffers, shaders, textures, pipeline state) and a way to use those resources to construct a frame by submitting some draw calls.
Try to keep any high-level logic out of the wrapper portion of the API. If you implement a clever scene culling technique in this portion of the API, well now you are on the hook to duplicate that logic in all of the backend implementations. That's a lot of extra effort, so keep it simple. Scene management should be part of a higher-level portion of the API that uses the wrapper rather than being part of the wrapper itself.
Choose the targets you will support and understand them. It's hard to write decent wrappers for "everything," and you probably don't need to (arguably you don't need to write a single wrapper, either, as noted in Philipp's answer). It's almost impossible to write a decent wrapper if you don't know the APIs you're going to wrap already.
Evaluate the state of your API regularly. It should in general have a smaller surface area than the underlying wrapped APIs; if you find yourself creating one-to-one wrapper types for every D3D structure or every OpenGL function call you are probably veering off course.
Look at what work has gone before. Sokol and BGFX are APIs that provide levels of agnosticism that may be useful to you, and are relatively easy to understand (the former especially).
answered Nov 30 at 16:43
Josh♦
91.6k16205322
91.6k16205322
add a comment |
add a comment |
up vote
2
down vote
Another point not yet mentioned which you should consider is what your performance goals are. If your goal is to have a graphics library that will yield good performance out of a cheap hardware platform, but also be usable on a variety of platforms that are vastly more powerful but use a different API, it may make sense to design your API around whatever abstractions are used natively on the platform where performance is an issue. Even if this causes a 50% speed degradation on the more powerful platforms, it may be worth it if it allows a 20% speed improvement on the platform where performance matters most.
add a comment |
up vote
2
down vote
Another point not yet mentioned which you should consider is what your performance goals are. If your goal is to have a graphics library that will yield good performance out of a cheap hardware platform, but also be usable on a variety of platforms that are vastly more powerful but use a different API, it may make sense to design your API around whatever abstractions are used natively on the platform where performance is an issue. Even if this causes a 50% speed degradation on the more powerful platforms, it may be worth it if it allows a 20% speed improvement on the platform where performance matters most.
add a comment |
up vote
2
down vote
up vote
2
down vote
Another point not yet mentioned which you should consider is what your performance goals are. If your goal is to have a graphics library that will yield good performance out of a cheap hardware platform, but also be usable on a variety of platforms that are vastly more powerful but use a different API, it may make sense to design your API around whatever abstractions are used natively on the platform where performance is an issue. Even if this causes a 50% speed degradation on the more powerful platforms, it may be worth it if it allows a 20% speed improvement on the platform where performance matters most.
Another point not yet mentioned which you should consider is what your performance goals are. If your goal is to have a graphics library that will yield good performance out of a cheap hardware platform, but also be usable on a variety of platforms that are vastly more powerful but use a different API, it may make sense to design your API around whatever abstractions are used natively on the platform where performance is an issue. Even if this causes a 50% speed degradation on the more powerful platforms, it may be worth it if it allows a 20% speed improvement on the platform where performance matters most.
answered Nov 30 at 17:23
supercat
43724
43724
add a comment |
add a comment |
Thanks for contributing an answer to Game Development Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgamedev.stackexchange.com%2fquestions%2f165761%2fhow-do-i-know-if-im-abstracting-graphics-apis-too-tightly%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
5
Are you 100% certain that your wrapper + Vulkan or D3D11 is faster than just always using OpenGL?
– Mooing Duck
Nov 30 at 22:58
@Mooing Duck if used correctly, yes.
– Gabriele Vierti
Dec 1 at 7:34
3
I would seriously doubt that. Most of the gains in Vulkan come from being very low-level and doing things in a very peculiar, specific way. Something that is generic enough to also do the same seamlessly in OpenGL or D3D almost certainly can't do that. Reimplementing the same stuff as OpenGL does (like many Vulkan tutorials do, ironically) results in 99.99% the same performance, with 20 times the work.
– Damon
Dec 1 at 15:46
@Damon that's right, but newer APIs are specifically designed (and not adapted like OpenGL) to work on modern gpus; speaking of Vulkan, you can pretty much use the same API on every supported platform, contrarily to OpenGL, where you need to use the "Embedded Systems" version. Other than less cpu overhead and fancy features we don't have much, but in the future we might have some pretty surprising techniques that may run faster using Vk or D3D12 rather than OGL or D3D11
– Gabriele Vierti
Dec 1 at 16:04