Sign in to follow this  
Medo Mex

DX11 Supporting Multiple DirectX Versions

Recommended Posts

Medo Mex    891

Hello,

 

I have interface IRenderer, two classes are derived from this interface IDX9Renderer and IDX11Renderer.

 

Now, I'm trying to be able to support either DX9 or DX11 in my engine

 

So my question is: How IRenderer interface structure should look like?

 

For example:

IRenderer::createVertexBuffer(...);
IRenderer::draw(...);

What to put in the above methods as a parameter so I can use it in both classes IDX9Renderer and IDX11Renderer?

Edited by Medo3337

Share this post


Link to post
Share on other sites
cozzie    5029
If you want to follow this path, you need to create functions in the renderer class that apply to both the dx9 and dx11 inherited classes. Everything dx9/dx11 specific you can add (members and functions) to the inherited classes.

Just out of curiosity, why go though this at all? Since all gpu's from 3 years old and younger (by head) support dx11. Plus windows xp isn't supported anymore (and I believe not often used among gamers). Of course if it's just for practice then it's another case.

I created an engine which I've been working on for years using dx9. But it's set up quite modular and flexible so later on I can "update" it to dx11.

Share this post


Link to post
Share on other sites
Medo Mex    891

@cozzie: The reason why is that I want to be able to add any future version of DirectX to the engine.

 

I'm still not sure what the correct rendering interface IRenderer should look like.

Share this post


Link to post
Share on other sites
cozzie    5029
class IRenderer
{
// generic renderer stuff
}

class IDirectX9Renderer : public IRenderer
{
// specific dx9 stuff
}

If this is not what you're looking for, then maybe can you be a bit more specific.

Share this post


Link to post
Share on other sites
Medo Mex    891

@cozzie: That's already what I have, now I'm not sure what the correct parameters that I should put here so I can support multiple version of DX:

IRenderer::createVertexBuffer(...);
IRenderer::createIndexBuffer(...);
IRenderer::draw(...);

Share this post


Link to post
Share on other sites
ryan20fun    2635

 

@cozzie: That's already what I have, now I'm not sure what the correct parameters that I should put here so I can support multiple version of DX:

IRenderer::createVertexBuffer(...);
IRenderer::createIndexBuffer(...);
IRenderer::draw(...);

I would say that you should start by doing a low level abstraction of the one you want your interface to emulate.

 

Right now I have a "ResourceCreator" class that you can get after you load the library(DLL), This in tern is used to create any type of resource that is supported.

 

An example of my index buffer's create method(I do need to make alowance for 2byte indices):

/*! This creates the vertex buffer with the specified number of elements and in the specified memory pool.
*
*	Parameters:
*		Elements	: The number of elements of length of sizeof( pIndices[ 0 ] ).
*		pIndices	: A pointer to the index data to use for creation.
*		Topology	: How the elements will be use to create the rendering surface.
*		Usage		: The usage pattern to apply to this resource.
*		CPUAccess	: What access should the CPU have to this resource.
*/
DLLEXPORT virtual HRESULT Create( const unsigned Elements, const unsigned* pIndices,
								  const PrimitiveTopology Topology = PrimitiveTopology::TriangleList,
								  const UsageType Usage = UsageType::Immutable,
								  const CPUAccess CPUAccess = CPUAccess::None ) = NOT_IMPLEMENTED;


And the vertex buffer:

/*! This creates the vertex buffer with the specified number of elements.
*
*	Parameters:
*		Elements	: The number of elements of length of Description.length().
*		Description	: The layout of each element in memory.
*		pVertices	: A pointer to the vertex data to use for creation.
*		Usage		: The usage pattern to apply to this resource.
*		CPUAccess	: What access should the CPU have to this resource.
*/
DLLEXPORT virtual HRESULT Create( const unsigned Elements, const Vertex::Layout Description,
								  const void* pVertices, UsageType Usage = UsageType::Immutable,
								  const CPUAccess CPUAccess = CPUAccess::None ) = NOT_IMPLEMENTED;

HTH

Ryan.

Share this post


Link to post
Share on other sites
Alessio1989    4634

What is the purpose of DX9 support? If it is for old hardware instead of Windows XP you can use Direct3D feature levels to target SM 2.x and SM 3.0 GPUs (keep in mind that you will unable to use SM 3.0 features) https://msdn.microsoft.com/en-us/library/ff476876.aspx

 

Otherwise as suggested you should write different rendering path for D3D9 and D3D11 (write you own graphics API could be really challenging since DX9 and DX11 are really different in features).

Edited by Alessio1989

Share this post


Link to post
Share on other sites
Juliean    7077


Just out of curiosity, why go though this at all? Since all gpu's from 3 years old and younger (by head) support dx11. Plus windows xp isn't supported anymore (and I believe not often used among gamers). Of course if it's just for practice then it's another case.

 


What is the purpose of DX9 support?

 

As of Dezember 2014, Windows XP still holds 18,26% of market share according to this site:

 

http://www.netmarketshare.com/operating-system-market-share.aspx?qprid=10&qpcustomd=0

 

I don't know how much of those 18,26% are gamers, but it based on those numbers it could still be viable to support XP to get an increased userbase.

Edited by Juliean

Share this post


Link to post
Share on other sites
Brain    18906

I don't know how much of those 18,26% are gamers

 

I'm not sure I'd trust these figures at all for gaming metrics, as it is based on Web browser useragent strings which are not relevant to what we are doing.

 

On the other hand steam records much better statistics of operating system usage: http://store.steampowered.com/hwsurvey

 

Edit: this shows about 4% XP users, 32 and 64 bit combined...

Edited by braindigitalis

Share this post


Link to post
Share on other sites
Medo Mex    891

Right now there is a problem:

 

vs_4_0 is working in DX11 but NOT working in DX9

vs_3_0 is NOT working in DX11 but working in DX9

 

NOT working means HRESULT (E_FAIL) When calling Device::CreateVertexBuffer()

 

Why?

Share this post


Link to post
Share on other sites
ryan20fun    2635

Right now there is a problem:

 

vs_4_0 is working in DX11 but NOT working in DX9

vs_3_0 is NOT working in DX11 but working in DX9

 

NOT working means HRESULT (E_FAIL) When calling Device::CreateVertexBuffer()

 

Why?

Those are Vertex Shader versions, I do not see how that is affecting the creation of a Vertex Buffer.

 

Can you show the some code on how you are creating the resources?

 

If you have further issues I can post the relevent (sections of) code that I use.

 

HTH

Ryan.

Share this post


Link to post
Share on other sites
Medo Mex    891

@ryan20fun: The following doesn't work, if I changed LPCSTR pProfile parameter from vs_3_0 to vs_4_0 it will work

 ID3D10Blob *VS, *PS;
 D3DX11CompileFromFile("shader.fx", 0, 0, "VS", "vs_3_0", 0, 0, 0, &VS, 0, 0);
 D3DX11CompileFromFile("shader.fx", 0, 0, "PS", "ps_3_0", 0, 0, 0, &PS, 0, 0);

 device->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
 device->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

Share this post


Link to post
Share on other sites
ryan20fun    2635

 

@ryan20fun: The following doesn't work, if I changed LPCSTR pProfile parameter from vs_3_0 to vs_4_0 it will work

 ID3D10Blob *VS, *PS;
 D3DX11CompileFromFile("shader.fx", 0, 0, "VS", "vs_3_0", 0, 0, 0, &VS, 0, 0);
 D3DX11CompileFromFile("shader.fx", 0, 0, "PS", "ps_3_0", 0, 0, 0, &PS, 0, 0);

 device->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
 device->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

Hmm, I think it has to do with feature level( I have never tried using vs_3_0 before).

What happens if you use downleveled feature level like D3D_FEATURE_LEVEL_9_3?

 

Would it hurt to just use vs_4_0 when using D3D10+ ?

 

Unfortunetly I only used the Fixed Funciton Pipeline with D3D9, So I can not help you with any pointers with making a interface that would require minimal changes to use D3D9.

 

HTH

Ryan.

Share this post


Link to post
Share on other sites
Medo Mex    891

I guess D3D11 doesn't support vs_3_0 / ps_3_0.

 

There is something I'm not sure if I'm doing correctly.

 

For vertex buffers, D3D9 uses IDirect3DVertexBuffer9 while D3D11 uses ID3D11Buffer

 

What is the correct way to create a struct that handle both so I can use it in IRenderer?

 

Here is what I have right now:

struct EngineVertexBuffer
{
       ID3D11Buffer *D3D9_VB;
       IDirect3DVertexBuffer9 *D3D11_VB;
};

Share this post


Link to post
Share on other sites
Alessio1989    4634

@ryan20fun: The following doesn't work, if I changed LPCSTR pProfile parameter from vs_3_0 to vs_4_0 it will work

 ID3D10Blob *VS, *PS;
 D3DX11CompileFromFile("shader.fx", 0, 0, "VS", "vs_3_0", 0, 0, 0, &VS, 0, 0);
 D3DX11CompileFromFile("shader.fx", 0, 0, "PS", "ps_3_0", 0, 0, 0, &PS, 0, 0);

 device->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
 device->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

 
 

 

@ryan20fun: The following doesn't work, if I changed LPCSTR pProfile parameter from vs_3_0 to vs_4_0 it will work

 ID3D10Blob *VS, *PS;
 D3DX11CompileFromFile("shader.fx", 0, 0, "VS", "vs_3_0", 0, 0, 0, &VS, 0, 0);
 D3DX11CompileFromFile("shader.fx", 0, 0, "PS", "ps_3_0", 0, 0, 0, &PS, 0, 0);

 device->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
 device->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
Hmm, I think it has to do with feature level( I have never tried using vs_3_0 before).
What happens if you use downleveled feature level like D3D_FEATURE_LEVEL_9_3?
 
Would it hurt to just use vs_4_0 when using D3D10+ ?
 
Unfortunetly I only used the Fixed Funciton Pipeline with D3D9, So I can not help you with any pointers with making a interface that would require minimal changes to use D3D9.
 
HTH
Ryan.

 


D3D_FEATURE_LEVEL_9_3 does NOT support shader model 3, only SM 2.x.
 
Here are the correct shader compiler targets for Direct3D10Level9 feature levels (applies to DX10.1 and DX11.x, and I can guess the upcoming DX12): https://msdn.microsoft.com/en-us/library/jj215820.aspx#direct3d_9.1__9.2__and_9.3_feature_levels

Edited by Alessio1989

Share this post


Link to post
Share on other sites
ryan20fun    2635

 

For vertex buffers, D3D9 uses IDirect3DVertexBuffer9 while D3D11 uses ID3D11Buffer

 

What is the correct way to create a struct that handle both so I can use it in IRenderer?

 

Here is what I have right now:

struct EngineVertexBuffer
{
      ID3D11Buffer *D3D9_VB;
      IDirect3DVertexBuffer9 *D3D11_VB;
};

 

I would use two different implementations, But if you want to have one implementation to hold both versions for some reason then I would use a union and some type of global variable denotating which one to use.

 

So it would be:

class VertexBuffer : public GraphicsResource
{
  public:
     void*           GetObject() const;
     SomeVariable    GetVersion() const;

  private:
     union
     {
          ID3D11Buffer*             VB11;
          IDirect3DVertexBuffer9*   VB9;
     } u;
     SomeVariable     m_DirectXVersion;
}

HTH

Ryan.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By gomidas
      I am trying to add normal map to my project I have an example of a cube: 
      I have normal in my shader I think. Then I set shader resource view for texture (NOT BUMP)
                  device.ImmediateContext.PixelShader.SetShaderResource(0, textureView);             device.ImmediateContext.Draw(VerticesCount,0); What should I do to set my normal map or how it is done in dx11 generally example c++?
    • By fighting_falcon93
      Imagine that we have a vertex structure that looks like this:
      struct Vertex { XMFLOAT3 position; XMFLOAT4 color; }; The vertex shader looks like this:
      cbuffer MatrixBuffer { matrix world; matrix view; matrix projection; }; struct VertexInput { float4 position : POSITION; float4 color : COLOR; }; struct PixelInput { float4 position : SV_POSITION; float4 color : COLOR; }; PixelInput main(VertexInput input) { PixelInput output; input.position.w = 1.0f; output.position = mul(input.position, world); output.position = mul(output.position, view); output.position = mul(output.position, projection); output.color = input.color; return output; } And the pixel shader looks like this:
      struct PixelInput { float4 position : SV_POSITION; float4 color : COLOR; }; float4 main(PixelInput input) : SV_TARGET { return input.color; } Now let's create a quad consisting of 2 triangles and the vertices A, B, C and D:
      // Vertex A. vertices[0].position = XMFLOAT3(-1.0f, 1.0f, 0.0f); vertices[0].color = XMFLOAT4( 0.5f, 0.5f, 0.5f, 1.0f); // Vertex B. vertices[1].position = XMFLOAT3( 1.0f, 1.0f, 0.0f); vertices[1].color = XMFLOAT4( 0.5f, 0.5f, 0.5f, 1.0f); // Vertex C. vertices[2].position = XMFLOAT3(-1.0f, -1.0f, 0.0f); vertices[2].color = XMFLOAT4( 0.5f, 0.5f, 0.5f, 1.0f); // Vertex D. vertices[3].position = XMFLOAT3( 1.0f, -1.0f, 0.0f); vertices[3].color = XMFLOAT4( 0.5f, 0.5f, 0.5f, 1.0f); // 1st triangle. indices[0] = 0; // Vertex A. indices[1] = 3; // Vertex D. indices[2] = 2; // Vertex C. // 2nd triangle. indices[3] = 0; // Vertex A. indices[4] = 1; // Vertex B. indices[5] = 3; // Vertex D. This will result in a grey quad as shown in the image below. I've outlined the edges in red color to better illustrate the triangles:

      Now imagine that we’d want our quad to have a different color in vertex A:
      // Vertex A. vertices[0].position = XMFLOAT3(-1.0f, 1.0f, 0.0f); vertices[0].color = XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f);
      That works as expected since there’s now an interpolation between the black color in vertex A and the grey color in vertices B, C and D. Let’s revert the previus changes and instead change the color of vertex C:
      // Vertex C. vertices[2].position = XMFLOAT3(-1.0f, -1.0f, 0.0f); vertices[2].color = XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f);
      As you can see, the interpolation is only done half of the way across the first triangle and not across the entire quad. This is because there's no edge between vertex C and vertex B.
      Which brings us to my question:
      I want the interpolation to go across the entire quad and not only across the triangle. So regardless of which vertex we decide to change the color of, the color interpolation should always go across the entire quad. Is there any efficient way of achieving this without adding more vertices and triangles?
      An illustration of what I'm trying to achieve is shown in the image below:

       
      Background
      This is just a very brief explanation of the problems background in case that would make it easier for you to understand the problems roots and maybe help you with finding a better solution to the problem.
      I'm trying to texture a terrain mesh in DirectX11. It's working, but I'm a bit unsatisfied with the result. When changing the terrain texture of a single vertex, the interpolation with the other vertices results in a hexagon shape instead of a squared shape:

      As the red arrows illustrate, I'd like the texture to be interpolated all the way into the corners of the quads.
    • By -Tau-
      Hello, I'm close to releasing my first game to Steam however, my game keeps failing the review process because it keeps crashing. The problem is that the game doesn't crash on my computer, on my laptop, on our family computer, on fathers laptop and i also gave 3 beta keys to people i know and they said the game hasn't crashed.
      Steam reports that the game doesn't crash on startup but few frames after a level has been started.
      What could cause something like this? I have no way of debugging this as the game works fine on every computer i have.
       
      Game is written in C++, using DirectX 11 and DXUT framework.
    • By haiiry
      I'm trying to get, basically, screenshot (each 1 second, without saving) of Direct3D11 application. Code works fine on my PC(Intel CPU, Radeon GPU) but crashes after few iterations on 2 others (Intel CPU + Intel integrated GPU, Intel CPU + Nvidia GPU).
      void extractBitmap(void* texture) { if (texture) { ID3D11Texture2D* d3dtex = (ID3D11Texture2D*)texture; ID3D11Texture2D* pNewTexture = NULL; D3D11_TEXTURE2D_DESC desc; d3dtex->GetDesc(&desc); desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.Usage = D3D11_USAGE_STAGING; desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; HRESULT hRes = D3D11Device->CreateTexture2D(&desc, NULL, &pNewTexture); if (FAILED(hRes)) { printCon(std::string("CreateTexture2D FAILED:" + format_error(hRes)).c_str()); if (hRes == DXGI_ERROR_DEVICE_REMOVED) printCon(std::string("DXGI_ERROR_DEVICE_REMOVED -- " + format_error(D3D11Device->GetDeviceRemovedReason())).c_str()); } else { if (pNewTexture) { D3D11DeviceContext->CopyResource(pNewTexture, d3dtex); // Wokring with texture pNewTexture->Release(); } } } return; } D3D11SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast< void** >(&pBackBuffer)); extractBitmap(pBackBuffer); pBackBuffer->Release(); Crash log:
      CreateTexture2D FAILED:887a0005 DXGI_ERROR_DEVICE_REMOVED -- 887a0020 Once I comment out 
      D3D11DeviceContext->CopyResource(pNewTexture, d3dtex); 
      code works fine on all 3 PC's.
    • By Fluffy10
      Hi i'm new to this forum and was wondering if there are any good places to start learning directX 11. I bought Frank D Luna's book but it's really outdated and the projects won't even compile. I was excited to start learning from this book because it gives detailed explanations on the functions being used as well as the mathematics. Are there any tutorials / courses /books that are up to date which goes over the 3D math and functions in a detailed manner? Or where does anyone here learn directX 11? I've followed some tutorials from this website http://www.directxtutorial.com/LessonList.aspx?listid=11 which did a nice job but it doesn't explain what's happening with the math so I feel like I'm not actually learning, and it only goes up until color blending. Rasteriks tutorials doesn't go over the functions much at all or the math involved either. I'd really appreciate it if anyone can point me in the right direction, I feel really lost. Thank you
  • Popular Now