Jump to content

  • Log In with Google      Sign In   
  • Create Account

SamplerState in code or HLSL?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 KaiserJohan   Members   -  Reputation: 1158

Like
0Likes
Like

Posted 19 July 2014 - 05:14 PM

Hey, going from OpenGL 4 to DX11, and am currently stuck at uploading some diffuse textures to pixel shader.

 

1) I've seen code samples where you create a sampler object (kinda like in OpenGL?) in D3D code and I've also seen sampler types defined explicitly in the HLSL shader. Is there any reason to pick one over the other?

 

2) How are mipmaps created in DX11? In OpenGL, theres a function specifically generate mipmaps for a texture, and then you can set sampler parameters to use mipmaps when sampling the textures. How is this done in DX11?


Edited by KaiserJohan, 19 July 2014 - 05:18 PM.


Sponsor:

#2 MJP   Moderators   -  Reputation: 11372

Like
4Likes
Like

Posted 19 July 2014 - 06:21 PM

1. At a base level, D3D11 only supports creating sampler states on the application side using D3D API calls. Any HLSL code you've seen for defining sampler states was using the effects framework, which is a higher-level library that sits on top of core D3D. The effects framework actually reflects the sampler data from the compiled code, and uses that reflected data to create and bind sampler states behind the scenes. I really wouldn't recommend using the effects framework (it's old and no longer updated), so you should just create and bind sampler states manually. If necessary, you can always write your own layer for reflecting data from your shader and using that to control binding of samplers and textures.

 

2. D3D supports what's called "automatic mipmap generation", and it uses the GPU to generate the lower-resolution mip levels using the highest-resolution mip (level 0) as the source data. It's generally intended for generating mips for textures that are generated by the GPU during a frame, and not so much for generating mips for static textures created at load time. However you can use it that way, if you wish. To do it you need to create your texture using D3D11_USAGE_DEFAULT as the Usage, and D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET as the BindFlags. You also need to specify D3D11_RESOURCE_MISC_GENERATE_MIPS for MiscFlags. Make sure you also specify the correct number for MipLevels, or alternately specify 0 to get the full mip chain. When you call CreateTexture2D you can pass NULL for pInitialData, and after you've created it you can use UpdateSubresource to fill the texture with data for the first mip level. Once you've done that, you can create your shader resource view call ID3D11DeviceContext::GenerateMips to fill in the rest of the mip levels.

If you don't want to write this yourself and you're loading textures from a standard image format, you can grab WICTextureLoader.h/.cpp from DirectXTex and use that to load your textures. You can also just look at the code if you want an example of how to do what I described above.



#3 Mona2000   Members   -  Reputation: 602

Like
2Likes
Like

Posted 20 July 2014 - 08:17 AM

I really wouldn't recommend using the effects framework (it's old and no longer updated)

 

Not that I'm a fan of the effects framework, but it's still being updated.



#4 MJP   Moderators   -  Reputation: 11372

Like
0Likes
Like

Posted 20 July 2014 - 04:56 PM

 

I really wouldn't recommend using the effects framework (it's old and no longer updated)

 

Not that I'm a fan of the effects framework, but it's still being updated.

 

 

I stand corrected!



#5 KaiserJohan   Members   -  Reputation: 1158

Like
0Likes
Like

Posted 22 July 2014 - 04:17 PM

OK, I tried it as you suggested and had a look at the DirectTex code, but something must be wrong with the mipmaps. I have a large rectangular floor with a checker-like texture over it, but instead I get the following:

 

mipmap.jpg

 

 

Any reason why this could be?

 

I have the following to build the texture:

 

    DX11Texture::DX11Texture(ID3D11Device* device, ID3D11DeviceContext* context, const std::vector<uint8_t>& textureData, uint32_t textureWidth, uint32_t textureHeight, TextureType textureType, Logger& logger) :
        mTexture(nullptr), mShaderResourceView(nullptr), mTextureID(gNextTextureID++), mTextureType(textureType)
    {
        // create texture
        D3D11_TEXTURE2D_DESC textureDesc;
        ZeroMemory(&textureDesc, sizeof(D3D11_TEXTURE2D_DESC));
        textureDesc.Width = textureWidth;
        textureDesc.Height = textureHeight;
        textureDesc.ArraySize = 1;
        textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        textureDesc.SampleDesc.Count = 1;
        textureDesc.Usage = D3D11_USAGE_DEFAULT;
        textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
        textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
        DXCALL(device->CreateTexture2D(&textureDesc, NULL, &mTexture));


        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
        ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
        srvDesc.Format = textureDesc.Format;
        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
        srvDesc.Texture2D.MipLevels = -1;
        DXCALL(device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResourceView));


        // mip-level 0 data
        uint32_t sizeWidth = textureWidth * sizeof(uint8_t);
        context->UpdateSubresource(mTexture, 0, NULL, &textureData.at(0), sizeWidth, sizeWidth * textureHeight);


        context->GenerateMips(mShaderResourceView);
    }

Here's the sampler used:

 

        // create texture sampler
        D3D11_SAMPLER_DESC samplerDesc;
        ZeroMemory(&samplerDesc, sizeof(D3D11_SAMPLER_DESC));
        samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC;
        samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.MaxAnisotropy = mAnisotropicFiltering;
        samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
        samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
        DXCALL(mDevice->CreateSamplerState(&samplerDesc, &mTextureSampler));

Any ideas? Looks correct to me



#6 MJP   Moderators   -  Reputation: 11372

Like
2Likes
Like

Posted 22 July 2014 - 05:16 PM

You're calculating your pitch incorrectly. You're using a R8G8B8A8 format, so the size of each texel should be textureWidth * sizeof(uint8_t) * 4. You can also pass a value of 0 for "SrcDepthPitch", since you're not using a 3D texture.

 



#7 KaiserJohan   Members   -  Reputation: 1158

Like
0Likes
Like

Posted 22 July 2014 - 05:31 PM

Hmm... tried that, it now looks like this - one half is now not textured:

 

mipmap2.jpg

 

 

The alterations being:

        uint32_t sizeWidth = textureWidth * sizeof(uint8_t) * 4;
        context->UpdateSubresource(mTexture, 0, NULL, &textureData.at(0), sizeWidth, 0);

        context->GenerateMips(mShaderResourceView);

Must be something else?


Edited by KaiserJohan, 22 July 2014 - 05:48 PM.


#8 SIC Games   Members   -  Reputation: 617

Like
0Likes
Like

Posted 22 July 2014 - 10:01 PM

Hmm... tried that, it now looks like this - one half is now not textured:

 

mipmap2.jpg

 

 

The alterations being:

        uint32_t sizeWidth = textureWidth * sizeof(uint8_t) * 4;
        context->UpdateSubresource(mTexture, 0, NULL, &textureData.at(0), sizeWidth, 0);

        context->GenerateMips(mShaderResourceView);

Must be something else?

Just trying to take a swing in the ball park---try doing

context->UpdateSubresource(mTexture, 0, NULL, &textureData.at(0), textureHeight * sizeWidth, 0);

See what you get? You may be getting the texture width but not the whole image itself - the way it looks like. I had trouble viewing your image from this site.


Game Engine's WIP Videos - http://www.youtube.com/sicgames88


#9 KaiserJohan   Members   -  Reputation: 1158

Like
0Likes
Like

Posted 23 July 2014 - 05:54 PM

 

Hmm... tried that, it now looks like this - one half is now not textured:

 

mipmap2.jpg

 

 

The alterations being:

        uint32_t sizeWidth = textureWidth * sizeof(uint8_t) * 4;
        context->UpdateSubresource(mTexture, 0, NULL, &textureData.at(0), sizeWidth, 0);

        context->GenerateMips(mShaderResourceView);

Must be something else?

Just trying to take a swing in the ball park---try doing

context->UpdateSubresource(mTexture, 0, NULL, &textureData.at(0), textureHeight * sizeWidth, 0);

See what you get? You may be getting the texture width but not the whole image itself - the way it looks like. I had trouble viewing your image from this site.

 

 

It throws me an "Access violation reading location" exception. Though I can confirm textureData.size=65536 so thats strange?

 

Also, theres nothing with the way I create the two vertex buffers (one of vertices, one for texcoords)?

    DX11Mesh::DX11Mesh(ID3D11Device* device, const BYTE* shaderBytecode, const uint32_t shaderBytecodeSize, const std::vector<float>& vertexData, const std::vector<float>& normalData,
        const std::vector<float>& texCoords, const std::vector<float>& tangents, const std::vector<float>& bitangents, const std::vector<uint32_t>& indexData, Logger& logger) 
        : mLogger(logger), mMeshID(gNextMeshID++), mNumIndices(indexData.size()), mVertexBuffer(nullptr), mTexcoordBuffer(nullptr), mIndexBuffer(nullptr), mInputLayout(nullptr)
    {
        // vertex buffer
        D3D11_BUFFER_DESC bufferDescription;
        ZeroMemory(&bufferDescription, sizeof(D3D11_BUFFER_DESC));
        bufferDescription.Usage = D3D11_USAGE_IMMUTABLE;
        bufferDescription.ByteWidth = vertexData.size() * sizeof(float);
        bufferDescription.BindFlags = D3D11_BIND_VERTEX_BUFFER;

        D3D11_SUBRESOURCE_DATA initData;
        ZeroMemory(&initData, sizeof(D3D11_SUBRESOURCE_DATA));
        initData.pSysMem = &vertexData.at(0);

        DXCALL(device->CreateBuffer(&bufferDescription, &initData, &mVertexBuffer));

        // texcoord buffer
        ZeroMemory(&bufferDescription, sizeof(D3D11_BUFFER_DESC));
        bufferDescription.Usage = D3D11_USAGE_IMMUTABLE;
        bufferDescription.ByteWidth = texCoords.size() * sizeof(float);
        bufferDescription.BindFlags = D3D11_BIND_VERTEX_BUFFER;

        ZeroMemory(&initData, sizeof(D3D11_SUBRESOURCE_DATA));
        initData.pSysMem = &texCoords.at(0);

        DXCALL(device->CreateBuffer(&bufferDescription, &initData, &mTexcoordBuffer));

        // index buffer
        ZeroMemory(&bufferDescription, sizeof(D3D11_BUFFER_DESC));
        bufferDescription.Usage = D3D11_USAGE_IMMUTABLE;
        bufferDescription.ByteWidth = indexData.size() * sizeof(uint32_t);
        bufferDescription.BindFlags = D3D11_BIND_INDEX_BUFFER;

        ZeroMemory(&initData, sizeof(D3D11_SUBRESOURCE_DATA));
        initData.pSysMem = &indexData.at(0);

        DXCALL(device->CreateBuffer(&bufferDescription, &initData, &mIndexBuffer));

        // input layout
        D3D11_INPUT_ELEMENT_DESC inputDescription[2];
        ZeroMemory(&inputDescription, sizeof(D3D11_INPUT_ELEMENT_DESC) * 2);
        inputDescription[0].SemanticName = "POSITION";
        inputDescription[0].SemanticIndex = 0;
        inputDescription[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
        inputDescription[0].InputSlot = 0;
        inputDescription[0].AlignedByteOffset = 0;
        inputDescription[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
        inputDescription[0].InstanceDataStepRate = 0;
        inputDescription[1].SemanticName = "TEXCOORD";
        inputDescription[1].SemanticIndex = 0;
        inputDescription[1].Format = DXGI_FORMAT_R32G32_FLOAT;
        inputDescription[1].InputSlot = 0;
        inputDescription[1].AlignedByteOffset = 12;
        inputDescription[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
        inputDescription[1].InstanceDataStepRate = 0;

        DXCALL(device->CreateInputLayout(inputDescription, 2, shaderBytecode, shaderBytecodeSize, &mInputLayout));
    }

And this is how I bind them for drawing:

    void DX11Mesh::Draw(ID3D11DeviceContext* context)
    {
        uint32_t vertexSize = sizeof(float) * 3, texcoordSize = sizeof(float) * 2;
        uint32_t offset = 0;

        context->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexSize, &offset);
        context->IASetVertexBuffers(1, 1, &mTexcoordBuffer, &texcoordSize, &offset);
        context->IASetIndexBuffer(mIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
        context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
        context->IASetInputLayout(mInputLayout);

        context->DrawIndexed(mNumIndices, 0, 0);
    }



The actual texcoordinates are legit; I used them in OpenGL so unless the texture sampling is different (I think not) then it should be just fine...?



#10 unbird   Crossbones+   -  Reputation: 4981

Like
3Likes
Like

Posted 24 July 2014 - 06:43 AM

Since you're using a second vertex stream, the input layout should reflect that:
  inputDescription[1].InputSlot = 1;
  inputDescription[1].AlignedByteOffset = 0;
Such troubles are better analyzed with a graphics debugger where you can see if your texture upload succeeded and if your vertices are correct.

#11 KaiserJohan   Members   -  Reputation: 1158

Like
1Likes
Like

Posted 24 July 2014 - 11:43 AM

Since you're using a second vertex stream, the input layout should reflect that:

  inputDescription[1].InputSlot = 1;
  inputDescription[1].AlignedByteOffset = 0;
Such troubles are better analyzed with a graphics debugger where you can see if your texture upload succeeded and if your vertices are correct.

 

 

Thats it. Thanks.

 

The result is not as good as I hoped it to be, even with anisotropic filtering set to 16. Here's an example:

 

 

ansitropic.jpg

 

In the background you see its very blurry. Is there any way to get better visuals?


Edited by KaiserJohan, 24 July 2014 - 12:06 PM.


#12 MJP   Moderators   -  Reputation: 11372

Like
1Likes
Like

Posted 24 July 2014 - 01:03 PM

At the grazing angles the undersampling is going to be very extreme, and even 16 samples won't be enough. So you'll get either aliasing artifacts, or blurring due to the hardware using a lower-resolution mip level. You'll also get issues from the hardware using various approximations and "optimizations". Usually you can turn these off in the driver control panel. Typically they'll have some sort of "quality" slider that you can turn up to get better filtering results at the cost of additional performance.


Edited by MJP, 24 July 2014 - 03:03 PM.


#13 SIC Games   Members   -  Reputation: 617

Like
0Likes
Like

Posted 24 July 2014 - 01:27 PM

MJP is right and also It looks great by the way! There's different sampler states you can also use if you want a texture rendered differently like point sampling amongst others. What are your settings for your device upon initialization? My sample count is 8 and sample quality is 32 getting the 8x MSAA and I'm hooking it where the player can change the settings inside the options menu.. However, your texture suppose to look like that do to the furtherest edge away from the camera gets blurred. Let me show you an example of mine from my editor.

 

If you can see the checkboard texture is blurred at the end? It's using the same sampler like yours but the texture isn't streamed like yours.  So, you're looks normal like it should be.

 

Awesome job getting it solved!

 

Also, I have a hard time viewing your images so time so I have to go into Tamper Data to actually get the link - you can post images easily on here. Just click on attach files on the bottom of the reply. If you don't see the attach files above the add reply - click on Advanced Reply Options. Just helping out the next time whenever you post images.

Attached Thumbnails

  • AnsiscopicMSAA.PNG

Game Engine's WIP Videos - http://www.youtube.com/sicgames88


#14 KaiserJohan   Members   -  Reputation: 1158

Like
0Likes
Like

Posted 24 July 2014 - 05:39 PM

Sorry for all the persistant questions, there are just a couple of things left I need to clear up.

 

1) So there really is no way to achieve better visuals than the 16x anisotropic filtering when sampling textures? The image I posted still looks really muddled.

 

2) I create the textures with the usage flag D3D11_USAGE_DEFAULT. This dosn't feel optimal considering its a static texture, but I need it due to mipmap generation. Is there any performance issues with that usage versus D3D11_USAGE_IMMUTABLE, and is there any easy way of fixing it?






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS