New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand GraphicsProfile Beyond Reach/HiDef #1941

Open
tomspilman opened this Issue Aug 15, 2013 · 13 comments

Comments

Projects
None yet
6 participants
@tomspilman
Member

tomspilman commented Aug 15, 2013

We need to decide how to expand the existing GraphicsProfile system beyond the old Reach/HiDef options from XNA 4.

We have a few options:

  • Go back to cap bits.
  • Expand GraphicsProfile with more profiles.
  • Add a new FeatureLevel enum similar to DirectX feature levels.

Cap bits enable "full flexibility" but it puts the burden all on the end user to figure out what combinations of bits are common. I don't think anyone wants to go to cap bits... even if they say they do. This is what sucked about DX9 and what IMO still sucks about OpenGL.

I could see expanding the existing GraphicsProfile to support more profiles:

public enum GraphicsProfile
{
    XboxOne,
    PlayStation4,                    
    HiDef,
    MidDef,
    LowDef,
    Reach,
    Limited
}

Some special platform specific profiles could be nice, but maybe sticking to more generic profiles is better?

The final option here is just mimicking the feature level concept from DirectX. This is sort of what GraphicsProfile does albeit with only two levels. Having it as a new separate enum just gives us some flexibility to break with the old system.

With either feature levels or profiles we will still need to look at all the different platforms MonoGame targets and all the hardware variations and make some calls as to how to decide how to categorize any particular hardware device. We then need to clearly document these rules for developers.

@KonajuGames

This comment has been minimized.

Show comment
Hide comment
@KonajuGames

KonajuGames Aug 15, 2013

Contributor

FeatureLevel and GraphicsProfile guarantee certain features or capabilities
are present. We would need to define what these features and capabilities
are for OpenGL for each profile. At launch we would need to interrogate
OpenGL to see which features or extensions it supports on that platform and
match them against the predetermined list.​

Contributor

KonajuGames commented Aug 15, 2013

FeatureLevel and GraphicsProfile guarantee certain features or capabilities
are present. We would need to define what these features and capabilities
are for OpenGL for each profile. At launch we would need to interrogate
OpenGL to see which features or extensions it supports on that platform and
match them against the predetermined list.​

@tomspilman

This comment has been minimized.

Show comment
Hide comment
@tomspilman

tomspilman Aug 15, 2013

Member

We would need to define what these features and capabilities
are for OpenGL for each profile.

DX11 feature levels might be a good starting point, but I figure we'll still need to do some work.

We have to build some sort of huge spreadsheet of different MonoGame hardware target devices with specific features and limits. We then use that list to figure out what these levels/profiles should be and what criteria they are based on.

At launch we would need to interrogate OpenGL to see
which features or extensions it supports on that platform and
match them against the predetermined list.​

Exactly.

Surely we'll find some weirdo devices that don't fit any one profile/level perfectly... we just have to pick lowest common denominator with those and live with it.

You know another idea is to provide both feature levels and cap bits both. Use the feature levels for the broad level features... dive into cap bits for any game critical specific feature that doesn't always fit a common class of hardware.

Member

tomspilman commented Aug 15, 2013

We would need to define what these features and capabilities
are for OpenGL for each profile.

DX11 feature levels might be a good starting point, but I figure we'll still need to do some work.

We have to build some sort of huge spreadsheet of different MonoGame hardware target devices with specific features and limits. We then use that list to figure out what these levels/profiles should be and what criteria they are based on.

At launch we would need to interrogate OpenGL to see
which features or extensions it supports on that platform and
match them against the predetermined list.​

Exactly.

Surely we'll find some weirdo devices that don't fit any one profile/level perfectly... we just have to pick lowest common denominator with those and live with it.

You know another idea is to provide both feature levels and cap bits both. Use the feature levels for the broad level features... dive into cap bits for any game critical specific feature that doesn't always fit a common class of hardware.

@KonajuGames

This comment has been minimized.

Show comment
Hide comment
@KonajuGames

KonajuGames Aug 15, 2013

Contributor

You know another idea is to provide both feature levels and cap bits
both. Use the feature levels for the broad level features... dive into cap
bits for any game critical specific feature that doesn't always fit a
common class of hardware.

Like we are doing now for DXT support, PVRTC support, etc.​

Contributor

KonajuGames commented Aug 15, 2013

You know another idea is to provide both feature levels and cap bits
both. Use the feature levels for the broad level features... dive into cap
bits for any game critical specific feature that doesn't always fit a
common class of hardware.

Like we are doing now for DXT support, PVRTC support, etc.​

@tomspilman

This comment has been minimized.

Show comment
Hide comment
@tomspilman

tomspilman Aug 15, 2013

Member

Like we are doing now for DXT support, PVRTC support, etc.​

Right except this would be a public official API that any MonoGame user could access.

Member

tomspilman commented Aug 15, 2013

Like we are doing now for DXT support, PVRTC support, etc.​

Right except this would be a public official API that any MonoGame user could access.

@chaosnhatred

This comment has been minimized.

Show comment
Hide comment
@chaosnhatred

chaosnhatred Aug 15, 2013

Contributor

I perso ally like the idea of having more profiles. As xna is becoming eol.
I believe it is better to expand off of what Microsoft started and make
monogame better and achieve more then they originally intented, which is
what you guys have done :-)
On Aug 14, 2013 9:32 PM, "Tom Spilman" notifications@github.com wrote:

We need to decide how to expand the existing GraphicsProfile system
beyond the old Reach/HiDef options from XNA 4.

We have a few options:

  • Go back to cap bits.
  • Expand GraphicsProfile with more profiles.
  • Add a new FeatureLevel enum similar to DirectX feature levels.

Cap bits enable "full flexibility" but it puts the burden all on the end
user to figure out what combinations of bits are common. I don't think
anyone wants to go to cap bits... even if they say they do. This is what
sucked about DX9 and what IMO still sucks about OpenGL.

I could see expanding the existing GraphicsProfile to support more
profiles:

public enum GraphicsProfile
{
            XboxOne,
            PlayStation4,
    HiDef,
            MidDef,
            LowDef,
    Reach,
            Limited
}

Some special platform specific profiles could be nice, but maybe sticking
to more generic profiles is better?

The final real option here is just mimicking the feature level concept
from DirectX. This is sort of what GraphicsProfile does albeit with only
two levels. Having it as a new separate enum just gives us some flexibility
to break with the old system.

With either feature levels or profiles we will still need to look at all
the different platforms MonoGame targets and all the hardware variations
and make some calls as to how to decide how to categorize any particular
hardware device. We then need to clearly document these rules for
developers.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1941
.

Contributor

chaosnhatred commented Aug 15, 2013

I perso ally like the idea of having more profiles. As xna is becoming eol.
I believe it is better to expand off of what Microsoft started and make
monogame better and achieve more then they originally intented, which is
what you guys have done :-)
On Aug 14, 2013 9:32 PM, "Tom Spilman" notifications@github.com wrote:

We need to decide how to expand the existing GraphicsProfile system
beyond the old Reach/HiDef options from XNA 4.

We have a few options:

  • Go back to cap bits.
  • Expand GraphicsProfile with more profiles.
  • Add a new FeatureLevel enum similar to DirectX feature levels.

Cap bits enable "full flexibility" but it puts the burden all on the end
user to figure out what combinations of bits are common. I don't think
anyone wants to go to cap bits... even if they say they do. This is what
sucked about DX9 and what IMO still sucks about OpenGL.

I could see expanding the existing GraphicsProfile to support more
profiles:

public enum GraphicsProfile
{
            XboxOne,
            PlayStation4,
    HiDef,
            MidDef,
            LowDef,
    Reach,
            Limited
}

Some special platform specific profiles could be nice, but maybe sticking
to more generic profiles is better?

The final real option here is just mimicking the feature level concept
from DirectX. This is sort of what GraphicsProfile does albeit with only
two levels. Having it as a new separate enum just gives us some flexibility
to break with the old system.

With either feature levels or profiles we will still need to look at all
the different platforms MonoGame targets and all the hardware variations
and make some calls as to how to decide how to categorize any particular
hardware device. We then need to clearly document these rules for
developers.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1941
.

@tomspilman

This comment has been minimized.

Show comment
Hide comment
@tomspilman

tomspilman Aug 15, 2013

Member

We've had this discussion before, but what prompted it this time as the new independent blend state features. This only works on DX10.1 and above devices. There is no way to detect if you are running on a compatible device right now as HiDef is DX10 and up.

Member

tomspilman commented Aug 15, 2013

We've had this discussion before, but what prompted it this time as the new independent blend state features. This only works on DX10.1 and above devices. There is no way to detect if you are running on a compatible device right now as HiDef is DX10 and up.

@prollin

This comment has been minimized.

Show comment
Hide comment
@prollin

prollin Aug 27, 2013

Contributor

Broad feature levels (ala DirectX) on top of specific capabilities (could be designed after XNA 3.X GraphicsDeviceCapabilities class) is the way to go IMHO.
Being platform specific is not a good idea as it defeats the purpose of a cross platform library and reduce code portability.

Contributor

prollin commented Aug 27, 2013

Broad feature levels (ala DirectX) on top of specific capabilities (could be designed after XNA 3.X GraphicsDeviceCapabilities class) is the way to go IMHO.
Being platform specific is not a good idea as it defeats the purpose of a cross platform library and reduce code portability.

@tomspilman

This comment has been minimized.

Show comment
Hide comment
@tomspilman

tomspilman Mar 23, 2015

Member

FYI. DX12 adds a few more feature levels:

http://postimg.org/image/fd4kuk85v/

I keep thinking we need to adopt DirectX feature levels with maybe some better names than just using DX version numbers. The defined DX feature levels are:

  D3D_FEATURE_LEVEL_9_1
  D3D_FEATURE_LEVEL_9_2
  D3D_FEATURE_LEVEL_9_3
  D3D_FEATURE_LEVEL_10_0
  D3D_FEATURE_LEVEL_10_1
  D3D_FEATURE_LEVEL_11_0
  D3D_FEATURE_LEVEL_11_1
  D3D_FEATURE_LEVEL_12_0
  D3D_FEATURE_LEVEL_12_1

Since DX runs on all the same hardware OpenGL does, DX feature levels can apply to OpenGL too. So hardware that is 10.1 feature level will have all the OGL extensions to support those features.

A two tiered system where we mix caps and feature levels could work.

We expand on the GraphicsCapabilities class we have adding new flags. Eventually we make this class public. Then at initialization MonoGame would figure out the correct GraphicsDevice feature level by examining the GraphicsCapabilities settings.

Member

tomspilman commented Mar 23, 2015

FYI. DX12 adds a few more feature levels:

http://postimg.org/image/fd4kuk85v/

I keep thinking we need to adopt DirectX feature levels with maybe some better names than just using DX version numbers. The defined DX feature levels are:

  D3D_FEATURE_LEVEL_9_1
  D3D_FEATURE_LEVEL_9_2
  D3D_FEATURE_LEVEL_9_3
  D3D_FEATURE_LEVEL_10_0
  D3D_FEATURE_LEVEL_10_1
  D3D_FEATURE_LEVEL_11_0
  D3D_FEATURE_LEVEL_11_1
  D3D_FEATURE_LEVEL_12_0
  D3D_FEATURE_LEVEL_12_1

Since DX runs on all the same hardware OpenGL does, DX feature levels can apply to OpenGL too. So hardware that is 10.1 feature level will have all the OGL extensions to support those features.

A two tiered system where we mix caps and feature levels could work.

We expand on the GraphicsCapabilities class we have adding new flags. Eventually we make this class public. Then at initialization MonoGame would figure out the correct GraphicsDevice feature level by examining the GraphicsCapabilities settings.

@KonajuGames

This comment has been minimized.

Show comment
Hide comment
@KonajuGames

KonajuGames Mar 23, 2015

Contributor

The combined approach might work. And using the DirectX feature levels is a good start.

Contributor

KonajuGames commented Mar 23, 2015

The combined approach might work. And using the DirectX feature levels is a good start.

@nkast

This comment has been minimized.

Show comment
Hide comment
@nkast

nkast Nov 21, 2016

Contributor

My previous approach to this was to reflect the directX codes to GraphicsProfile and do checks like this:
bool has4RT = gd.GraphicsProfile >= GraphicsProfile.DX9_3;
The problems with that was that (int)HiDef is already = 1. This might cause problem with serialization (XNB format has a byte where 01=HiDef, otherwise Reach). On the other hand Enums can't implement interfaces like IComparable, so we can't have HiDef =1 and also support this kind of check. Also some Consoles might have a mixed set of features and we see modern GPU dropping features, so we can't always expect higher profiles being supersets of lower profiles.

GraphicsCapabilities will work but I would like something that can be implemented on XNA as well (probably using extensions or a garbage free struct).
ex:

bool has4RT = gd.GetMaxRenderTargets()>=4;
bool has4RT = gd.GetGraphicsCapabilities().MaxRenderTargets>=4;
bool has4RT = (new GraphicsCapabilities(gd.GraphicsProfile)).MaxRenderTargets>=4;

IMO, what we need to do is
-For Reach profile create a 9.1 device (instead of allowing any of 9.3,9.2,9.1).
-For HiDef profile create a 10.0 device (instead of allowing anything from 11.1 to 10.0) and enforce the XNA limitations (which are very close to 9.3). I don't know if it's possible to create a 9.3 device and check if all HiDef specs are supported as optional features) create a 9.3 device.
-Add a 9.3 profile which is very common on Mobile.
-Add a true 10.0 profile that supports all the MG expensions like 4.0 Shaders, HDR, 8192 textures, 8 RenderTargets, 2^32 – 1 vertices, etc.

Contributor

nkast commented Nov 21, 2016

My previous approach to this was to reflect the directX codes to GraphicsProfile and do checks like this:
bool has4RT = gd.GraphicsProfile >= GraphicsProfile.DX9_3;
The problems with that was that (int)HiDef is already = 1. This might cause problem with serialization (XNB format has a byte where 01=HiDef, otherwise Reach). On the other hand Enums can't implement interfaces like IComparable, so we can't have HiDef =1 and also support this kind of check. Also some Consoles might have a mixed set of features and we see modern GPU dropping features, so we can't always expect higher profiles being supersets of lower profiles.

GraphicsCapabilities will work but I would like something that can be implemented on XNA as well (probably using extensions or a garbage free struct).
ex:

bool has4RT = gd.GetMaxRenderTargets()>=4;
bool has4RT = gd.GetGraphicsCapabilities().MaxRenderTargets>=4;
bool has4RT = (new GraphicsCapabilities(gd.GraphicsProfile)).MaxRenderTargets>=4;

IMO, what we need to do is
-For Reach profile create a 9.1 device (instead of allowing any of 9.3,9.2,9.1).
-For HiDef profile create a 10.0 device (instead of allowing anything from 11.1 to 10.0) and enforce the XNA limitations (which are very close to 9.3). I don't know if it's possible to create a 9.3 device and check if all HiDef specs are supported as optional features) create a 9.3 device.
-Add a 9.3 profile which is very common on Mobile.
-Add a true 10.0 profile that supports all the MG expensions like 4.0 Shaders, HDR, 8192 textures, 8 RenderTargets, 2^32 – 1 vertices, etc.

@nkast

This comment has been minimized.

Show comment
Hide comment
@nkast

nkast Nov 21, 2016

Contributor

@KonajuGames At launch we would need to interrogate OpenGL to see which features or extensions it supports on that platform and match them against the predetermined list.​

One place to do that is GraphicsAdapter.IsProfileSupported() at #5312.
https://github.com/nkast/MonoGame/blob/d38941ff3c546dbde3fbc8d3da3dce5f3f84a06d/MonoGame.Framework/Graphics/GraphicsAdapter.Legacy.cs#L384-L387
I am not familiar with GL to implement it myself but the idea is to query GL for features from those two tables:
https://msdn.microsoft.com/en-us/library/windows/desktop/ff476876(v=vs.85).aspx
https://blogs.msdn.microsoft.com/shawnhar/2010/03/12/reach-vs-hidef/

GraphicsDeviceManager should also implement .RankDevices()/.FindBestDevice() to select the best adapter during .ApplyChanges() or throw NoSuitableGraphicsDeviceException when no device is found with the required Profile.

Contributor

nkast commented Nov 21, 2016

@KonajuGames At launch we would need to interrogate OpenGL to see which features or extensions it supports on that platform and match them against the predetermined list.​

One place to do that is GraphicsAdapter.IsProfileSupported() at #5312.
https://github.com/nkast/MonoGame/blob/d38941ff3c546dbde3fbc8d3da3dce5f3f84a06d/MonoGame.Framework/Graphics/GraphicsAdapter.Legacy.cs#L384-L387
I am not familiar with GL to implement it myself but the idea is to query GL for features from those two tables:
https://msdn.microsoft.com/en-us/library/windows/desktop/ff476876(v=vs.85).aspx
https://blogs.msdn.microsoft.com/shawnhar/2010/03/12/reach-vs-hidef/

GraphicsDeviceManager should also implement .RankDevices()/.FindBestDevice() to select the best adapter during .ApplyChanges() or throw NoSuitableGraphicsDeviceException when no device is found with the required Profile.

@Jjagg

This comment has been minimized.

Show comment
Hide comment
@Jjagg

Jjagg Feb 2, 2017

Contributor

I wrote up a suggestion for the implementation of the new system in #5451. I'll repost it here since this is better place for the discussion. This is following the two tiered caps system as suggested in this thread i.e. GraphicsProfile for broad caps and manually modifying GraphicsCapabilities for granular control.

In the following, when I say profile I mean GraphicsProfile and when I say caps I mean GraphicsCapabilities.

In short my suggestion is to replace (in terms of functionality) what currently is GraphicsProfile in GraphicsDeviceManager by a GraphicsCapabilities property, let's call it 'RequiredCaps'. The GraphicsProfile property will stay available for convenience and backwards compatibility, but there'll be no _graphicsProfile field in GraphicsDeviceManager. It will just act as a fast way to set the RequiredCaps. The setter will do something like _requiredCaps = MapProfileToCaps(value);.

As for getting GraphicsProfile, I suggest we store a GraphicsProfile field in GraphicsCapabilities. Not all caps will map to a profile anymore, so we add a 'Custom' GraphicsProfile. When a profile is set, it sets the corresponding caps and also sets the GraphicsCapabilities GraphicsProfile field. When a setter for any property in GraphicsCapabilities is called it sets a dirty flag (to flag that it needs checking when GraphicsDeviceManager.ApplyChanges is called) and sets the profile to 'Custom'. The GraphicsProfile getter will do return _requiredCaps.GraphicsProfile;.

When a device is created by GraphicsDeviceManager it tries to create a device that supports the RequiredCaps. For OpenGL that means checking entry points. For DX that means getting the minimum required feature level and check if it's supported. (For a fast check DX could map the GraphicsProfile in the GraphicsCapabilities to a feature level if it is not 'Custom'). The requiredCaps passed to GraphicsDevice for its creation are set as its capabilities (so it's not its actual capabilities, but a subset of them). Internally we'd check everything against those GraphicsCapabilities of a device. These should be internal, maybe even a readonly variant of GraphicsCapabilities to make sure they're not modified.

Contributor

Jjagg commented Feb 2, 2017

I wrote up a suggestion for the implementation of the new system in #5451. I'll repost it here since this is better place for the discussion. This is following the two tiered caps system as suggested in this thread i.e. GraphicsProfile for broad caps and manually modifying GraphicsCapabilities for granular control.

In the following, when I say profile I mean GraphicsProfile and when I say caps I mean GraphicsCapabilities.

In short my suggestion is to replace (in terms of functionality) what currently is GraphicsProfile in GraphicsDeviceManager by a GraphicsCapabilities property, let's call it 'RequiredCaps'. The GraphicsProfile property will stay available for convenience and backwards compatibility, but there'll be no _graphicsProfile field in GraphicsDeviceManager. It will just act as a fast way to set the RequiredCaps. The setter will do something like _requiredCaps = MapProfileToCaps(value);.

As for getting GraphicsProfile, I suggest we store a GraphicsProfile field in GraphicsCapabilities. Not all caps will map to a profile anymore, so we add a 'Custom' GraphicsProfile. When a profile is set, it sets the corresponding caps and also sets the GraphicsCapabilities GraphicsProfile field. When a setter for any property in GraphicsCapabilities is called it sets a dirty flag (to flag that it needs checking when GraphicsDeviceManager.ApplyChanges is called) and sets the profile to 'Custom'. The GraphicsProfile getter will do return _requiredCaps.GraphicsProfile;.

When a device is created by GraphicsDeviceManager it tries to create a device that supports the RequiredCaps. For OpenGL that means checking entry points. For DX that means getting the minimum required feature level and check if it's supported. (For a fast check DX could map the GraphicsProfile in the GraphicsCapabilities to a feature level if it is not 'Custom'). The requiredCaps passed to GraphicsDevice for its creation are set as its capabilities (so it's not its actual capabilities, but a subset of them). Internally we'd check everything against those GraphicsCapabilities of a device. These should be internal, maybe even a readonly variant of GraphicsCapabilities to make sure they're not modified.

@nkast

This comment has been minimized.

Show comment
Hide comment
@nkast

nkast Jun 28, 2017

Contributor

I tested XNA and MG with the following preferedBackBuffer sizes
{2048, 2049, 4096, 4097, 8192, 8193, 16384, 16385}.

XNA was able to create a device with up to 16384 pixels wide (the limit of my 11.1 card) even on Reach profile . On 16385 it throw an exception.
MG went up to 4096 on Reach profile (MG request a 9.1,9.2 or 9.3 FL) and up to 16384 or HiDef.

So this is +1 towards always creating the highest profile no matter what the profile is.

On the other hand, we might not be able to check & catch all limitations of a video card and that's what I like about creating a device with a specific feature level. Maybe we can add a property EmulateFeatureLevel or something like that to switch between the two behaviors, but I dinno anyone will notice it.

Contributor

nkast commented Jun 28, 2017

I tested XNA and MG with the following preferedBackBuffer sizes
{2048, 2049, 4096, 4097, 8192, 8193, 16384, 16385}.

XNA was able to create a device with up to 16384 pixels wide (the limit of my 11.1 card) even on Reach profile . On 16385 it throw an exception.
MG went up to 4096 on Reach profile (MG request a 9.1,9.2 or 9.3 FL) and up to 16384 or HiDef.

So this is +1 towards always creating the highest profile no matter what the profile is.

On the other hand, we might not be able to check & catch all limitations of a video card and that's what I like about creating a device with a specific feature level. Maybe we can add a property EmulateFeatureLevel or something like that to switch between the two behaviors, but I dinno anyone will notice it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment