Writing on a UAV in pixel shader - directx

I was doing some experiment with textures as UAV in pixel shader by writing some value on it, but I'm not seeing its effect in the next draw call when I bind the same texture again as an SRV.
Example shader:
RWTexture2D<unsigned int> uav;
Texture2D tex : register(t0);
// Vertex Shader
float4 VS( float4 Pos : POSITION ) : SV_POSITION
{
return Pos;
}
// Pixel Shader, draw1 warm up
float4 PS( float4 Pos : SV_POSITION ) : SV_Target
{
return float4( 1.0f, 1.0f, 0.0f, 1.0f ); // Yellow, with Alpha = 1
}
// Pixel Shader, we are writing onto the texture by binding it as an UAV, draw2
float4 PS1( float4 Pos : SV_POSITION ) : SV_Target
{
if((Pos.x %2) && (Pos.y %2))
{
uav[Pos.xy]=0xFF000000; //some color
}
else
{
uav[Pos.xy]=0x00FF0000; //some color
}
return float4( 1.0f, 0.0f, 0.0f, 1.0f );
}
// Pixel Shader, here we are accessing texture as an SRV, draw3
float4 PS2( float4 Pos : SV_POSITION ) : SV_Target
{
float4 x = tex[Pos.xy];
return x;
}
I can provide the app source code if required.

I enabled the debug layer. It was UAV format mismatch error. In the UAV description, I declared R8G8B8A8_UNORM as a format and I'm accessing the element as UINT in the shader.
description: D3D11 ERROR: ID3D11DeviceContext::Draw: The resource return type for component 0 declared in the shader code (UINT) is not compatible with the resource type bound to Unordered Access View slot 1 of the Pixel Shader unit (UNORM). This mismatch is invalid if the shader actually uses the view [ EXECUTION ERROR #2097372: DEVICE_UNORDEREDACCESSVIEW_RETURN_TYPE_MISMATCH]
Source code:
D3D11_UNORDERED_ACCESS_VIEW_DESC UAVdesc;
ZeroMemory( &SRVdesc, sizeof(SRVdesc));
UAVdesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM;
UAVdesc.ViewDimension=D3D11_UAV_DIMENSION_TEXTURE2D;
UAVdesc.Texture2D.MipSlice=0;
g_pd3dDevice->CreateUnorderedAccessView( g_pTexture, &UAVdesc, &g_pUAV);
Texture created :
D3D11_TEXTURE2D_DESC TextureData;
ZeroMemory( &TextureData, sizeof(TextureData) );
TextureData.ArraySize=1;
TextureData.Height=height;
TextureData.Width=width;
TextureData.Format=DXGI_FORMAT_R8G8B8A8_TYPELESS;
TextureData.CPUAccessFlags=0;
TextureData.BindFlags=D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET|D3D11_BIND_UNORDERED_ACCESS;
TextureData.MipLevels=1;
TextureData.MiscFlags=0;
TextureData.SampleDesc.Count=1;
TextureData.SampleDesc.Quality=0;
TextureData.Usage=D3D11_USAGE_DEFAULT;
D3D11_SUBRESOURCE_DATA InitialData;
ZeroMemory( &InitialData, sizeof(InitialData));
InitialData.pSysMem=pData;
InitialData.SysMemPitch=width * sizeof(UINT);
InitialData.SysMemSlicePitch=width * sizeof(UINT) * height;
g_pd3dDevice->CreateTexture2D( &TextureData, &InitialData, &g_pTexture);
Shader code is already given above.
Fix:
D3D11_UNORDERED_ACCESS_VIEW_DESC UAVdesc;
ZeroMemory( &SRVdesc, sizeof(SRVdesc));
**UAVdesc.Format=DXGI_FORMAT_R32_UINT;**
UAVdesc.ViewDimension=D3D11_UAV_DIMENSION_TEXTURE2D;
UAVdesc.Texture2D.MipSlice=0;
g_pd3dDevice->CreateUnorderedAccessView( g_pTexture, &UAVdesc, &g_pUAV);
confirmed by dumping texture in staging resource. Thanks guys.

Related

How to use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL correctly?

I am having issue while drawing my cube on the window. I don't see any graphics on the window. I see the following warning messages in visual studio:
D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader expects a Render Target View bound to slot 0, but the Render Target View was unbound during a call to Present. A successful Present call for DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL SwapChains unbinds backbuffer 0 from all GPU writeable bind points. [ EXECUTION WARNING #3146082:
D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader expects a Render Target View bound to slot 0, but none is bound. This is OK, as writes of an unbound Render Target View are discarded. It is also possible the developer knows the data will not be used anyway. This is only a problem if the developer actually intended to bind a Render Target View here. [ EXECUTION WARNING #3146081: DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET]
I created swapchain using the following API:
virtual IDXGISwapChain* SwapChain(HWND wnd)
{
HRESULT hr = S_OK;
IDXGISwapChain* swapchain = nullptr;
DXGI_SWAP_CHAIN_DESC desc;
ZeroMemory(&desc, sizeof(DXGI_SWAP_CHAIN_DESC));
desc.Windowed = TRUE; // Sets the initial state of full-screen mode.
desc.BufferCount = 2;
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.SampleDesc.Count = 1; //multisampling setting
desc.SampleDesc.Quality = 0; //vendor-specific flag
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.OutputWindow = wnd;
// Create the DXGI device object to use in other factories, such as Direct2D.
IDXGIDevice3* dxgiDevice;
hr = device_->QueryInterface(__uuidof(IDXGIDevice3), reinterpret_cast<void**>(&dxgiDevice));
if (FAILED(hr))
return nullptr;
// Create swap chain.
IDXGIAdapter* adapter;
IDXGIFactory* factory;
hr = dxgiDevice->GetAdapter(&adapter);
dxgiDevice->Release();
if (FAILED(hr))
return nullptr;
adapter->GetParent(IID_PPV_ARGS(&factory));
hr = factory->CreateSwapChain(device_, &desc, &swapchain);
adapter->Release();
factory->Release();
return swapchain;
}
Render Target is bound using the call:
m_d3dDevice.Context()->OMSetRenderTargets(1, &m_pRenderTarget, , _pDepthStencilView);
The Present is implemented as:
swap_chain->Present(0, 0);
The shader code is:
cbuffer ConstantBuffer : register(b0)
{
matrix World;
matrix View;
matrix Projection;
float4 vLightDir[2];
float4 vLightColor[2];
float4 vOutputColor;
}
struct VS_INPUT
{
float4 Pos : POSITION;
float3 Norm : NORMAL;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float3 Norm : TEXCOORD0;
};
PS_INPUT VS(VS_INPUT input)
{
PS_INPUT output = (PS_INPUT)0;
output.Pos = mul(input.Pos, World);
output.Pos = mul(output.Pos, View);
output.Pos = mul(output.Pos, Projection);
output.Norm = mul(float4(input.Norm, 1), World).xyz;
return output;
}
float4 PS(PS_INPUT input) : SV_Target
{
float4 finalColor = 0;
//do NdotL lighting for 2 lights
for (int i = 0; i < 2; i++)
{
finalColor += saturate(dot((float3)vLightDir[i],input.Norm) * vLightColor[i]);
}
finalColor.a = 1;
return finalColor;
}
float4 PSSolid(PS_INPUT input) : SV_Target
{
return vOutputColor;
}
Invoke ID3D11DeviceContext::OMSetRenderTargets(...) before each rendering
// Add this before each rendering
spImCtx->OMSetRenderTargets(1, spRTV.GetAddressOf(), spZView.Get());
// clear
spImCtx->ClearRenderTargetView(spRTV.Get(), Colors::Black);
spImCtx->ClearDepthStencilView(spZView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
// drawing...
// swap
spSwapChain->Present(1, 0);

Vertex color is not interpolated in the context of ID3DXLine

I've created a standard Win32 DirectX9 window and I'm rendering to it using a custom effect, however I have a problem where the colours of vertices are not interpolated in the result.
void CRender::Begin()
{
perf.begin();
// Capture device state so it can be restored later.
// We use ID3DXLine::Begin() to fix some bugs that I don't know how to fix.
mpLine->Begin();
// Setup shader
shader.Begin( static_cast<float>(FloatTime()) );
}
void CRender::End()
{
// Reverse order of Begin()
shader.End();
mpLine->End();
}
The problem here lies with mpLine->Begin(), without calling this I get a perfectly nice interpolated triangle, with it the whole triangle has the same colour as the first vertex.
Image for clarification: http://i.imgur.com/vKN4SnE.png
I am using ID3DXLine::Begin() just to set up the device state for me. The reason I am using it is because I'm rendering in the context of another program (a game) by hooking its EndScene(). The game may leave the device in an unusable state causing rendering glitches in my overlay, all these problems go away when using ID3DXLine::Begin() except vertex colours aren't interpolated any more.
Vertex declaration:
// Create the vertex declaration for use with the shaders.
static const D3DVERTEXELEMENT9 vformat[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
{ 0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
D3DDECL_END()
};
HRESULT hr = dev->CreateVertexDeclaration( vformat, &decl );
Effect source:
// Vertex shader input
struct VSIN
{
float2 coord : POSITION;
float4 color : COLOR0;
float2 tex : TEXCOORD0;
};
// Vertex shader output / Pixel shader input
struct VSOUT
{
float4 coord : POSITION;
float4 color : COLOR0;
float2 tex : TEXCOORD0;
float2 pos : TEXCOORD1;
};
uniform float2 screen;
uniform float2x4 project;
float4 vstransform( float2 coord, const float2 shift )
{
float2 final = ( mul( project, float4(coord.x,coord.y,1,1) ) + shift ) * 2 / screen;
return float4( final.x-1, 1-final.y, 0, 1 );
}
VSOUT vsfix( VSIN data )
{
VSOUT vert;
const float2 shift = { -0.5f, -0.5f };
vert.coord = vstransform( data.coord, shift );
vert.color = data.color;
vert.tex = data.tex;
vert.pos = vert.coord.xy;
return vert;
}
float4 diffuse( VSOUT vert ) : COLOR
{
float4 px = vert.color;
return px;
}
technique Diffuse
{
pass p0
{
PixelShader = compile ps_2_0 diffuse();
VertexShader = compile vs_2_0 vsfix();
}
}

How to pass textures to DirectX 9 pixel shader?

I have pixel shader
// fxc.exe tiles.fs /T ps_3_0 /Fotiles.fsc /Fctiles.fsl
struct PSInput
{
float4 Pos : TEXCOORD0;
float3 Normal : TEXCOORD1;
float2 TexcoordUV : TEXCOORD2;
float2 TexcoordST : TEXCOORD3;
};
sampler2D sampler0; //uniform
sampler2D sampler1; //uniform
sampler2D sampler2; //uniform
sampler2D sampler3; //uniform
sampler2D alphamap1;//uniform
sampler2D alphamap2;//uniform
sampler2D alphamap3;//uniform
uniform int tex_count = 0;
uniform float4 color_ambient = float4(0.75, 0.75, 0.75, 1.0);
uniform float4 color_diffuse = float4(0.25, 0.25, 0.25, 1.0);
uniform float4 color_specular = float4(1.0, 1.0, 1.0, 1.0);
uniform float shininess = 77.0f;
uniform float3 light_position = float3(12.0f, 32.0f, 560.0f);
float4 main(PSInput In) : COLOR
{
float3 light_direction = normalize(light_position - (float3)In.Pos);
float3 normal = normalize(In.Normal);
float3 half_vector = normalize(light_direction + normalize((float3)In.Pos));
float diffuse = max(0.0, dot(normal, light_direction));
float specular = pow(max(0.0, dot(In.Normal, half_vector)), shininess);
float4 color = tex2D(sampler0, In.TexcoordUV);
if (tex_count > 0){
float4 temp = tex2D(sampler1, In.TexcoordUV);
float4 amap = tex2D(alphamap1, In.TexcoordST);
color = lerp(color, temp, amap.a);
}
if (tex_count > 1){
float4 temp = tex2D(sampler2, In.TexcoordUV);
float4 amap = tex2D(alphamap2, In.TexcoordST);
color = lerp(color, temp, amap.a);
}
if (tex_count > 2){
float4 temp = tex2D(sampler3, In.TexcoordUV);
float4 amap = tex2D(alphamap3, In.TexcoordST);
color = lerp(color, temp, amap.a);
}
color = color * color_ambient + diffuse * color_diffuse + specular * color_specular;
return color;
}
vertex shader
// fxc.exe tiles.vs /T vs_3_0 /Fotiles.vsc /Fctiles.vsl
struct VSInput
{
float3 Pos : POSITION;
float3 Normal : NORMAL;
float2 TexcoordUV : TEXCOORD0;
float2 TexcoordST : TEXCOORD1;
};
struct PSInput
{
float4 Pos : POSITION;
float3 Normal : TEXCOORD0;
float2 TexcoordUV : TEXCOORD1;
float2 TexcoordST : TEXCOORD2;
};
uniform matrix modelMatrix;
uniform matrix projectionMatrix;
uniform matrix lookAtMatrix;
PSInput main(VSInput In)
{
PSInput Out = (PSInput) 0;
//projectionMatrix * lookAtMatrix * modelMatrix;
matrix MVP = mul(modelMatrix, lookAtMatrix);
MVP = mul(MVP, projectionMatrix);
Out.Normal = mul(In.Normal, (float3x3)modelMatrix);
Out.Pos = mul(float4(In.Pos, 1.0), MVP);
Out.TexcoordUV = In.TexcoordUV;
Out.TexcoordST = In.TexcoordST;
return Out;
}
same works under OpenGL + GLSL except mix replaced by lerp (I hope its correct).
By example from http://www.two-kings.de/tutorials/dxgraphics/dxgraphics18.html I passing textures with:
ps_pConstantTable.SetInt(m_pD3DDevice, texCountHandle, 0);
for i := 0 to texCount - 1 do begin
tBlp := texture_buf[cx, cy][i];
if tBlp = nil then
break;
m_pD3DDevice.SetTexture(i, tBlp.itex);
ps_pConstantTable.SetInt(m_pD3DDevice, texCountHandle, i);
if i > 0 then begin
// this time, use blending:
m_pD3DDevice.SetTexture(i + 3, AlphaMaps[cx, cy][i]);
end;
end;
so ordinal textures have indices 0-3 and alpha 4-6 (max texCount 4).
The problem is: I can see mesh (terrain) but it is solid black. Am I need something else to set (without shaders it also was black until I assigned materials and light)? Can I pass textures like that? Can I do this with sampler2D as uniform (how)?
Edit: example with sources, shaders, several used textures and alphamaps, vertex data with normals at filebeam http://fbe.am/nm4 added. As small as possible. Also contains DXErr9ab.dll to log errors.
To use texture in pixel shader, you may following below steps
Create texture in your C/C++ file by D3DXCreateTextureFromFile or other functions.
if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "FaceTexture.jpg",
&g_pTexture ) ) )
return E_FAIL;
Declare a D3DXHANDLE and associate it with the texture in your shader file.(you should compile your effect file before this step, effects_ here is a pointer to ID3DXEffect)
texture_handle = effects->GetParameterByName(0, "FaceTexture");
Set the texture in render function
effects_->SetTexture(texture_handle, g_pTexture);
Declare a texture in your shader file
texture FaceTexture;
Declare a sampler in your shader file
// Face texture sampler
sampler FaceTextureSampler = sampler_state
{
Texture = <FaceTexture>;
MipFilter = LINEAR;
MinFilter = LINEAR;
MagFilter = LINEAR;
};
Do sampling in your pixel shader function
float4 BasicPS(OutputVS outputVS) : COLOR
{
float4 Output;
Output = FaceTexture.Sample(FaceTextureSampler, outputVS.texUV);
return Output;
}
If you have DirectX SDK installed, I recommend you to take a look at the sample "BasicHLSL" which has a very basic introduction of Vertex shader and Pixel shader(including texture).

HLSL point sprite texture coordinates work on ATI not NVIDIA

I am really stuck on this one. My HLSL for rendering point sprites with texture coordinates for a sprite sheet works fine on all ATI cards but not on any NVIDIA cards. On NVIDIA cards the passed texture coordinates map to the whole sprite sheet rather than a portion of it. Strange but it works fine on ATI cards. Am I missing something unique to ATI cards?
Here is my shader
struct VS_INPUT
{
float4 Position : POSITION;
float4 Color : COLOR;
float4 Texture : TEXCOORD0;
//float1 Psize : PSIZE0;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COLOR;
float2 Texture : TEXCOORD0;
float2 Texture_zw : TEXCOORD1;
float1 Psize : PSIZE;
};
float4x4 WorldViewProj;
texture Tex <string name = "sprite_coin_test.dds";>;
sampler2D s_2D;
float offset_x=0.0;
float offset_y=0.0;
sampler S0 = sampler_state
{
Texture = (Tex);
MinFilter = ANISOTROPIC; //LINEAR;
MagFilter = ANISOTROPIC; //LINEAR;
MipFilter = LINEAR;
};
VS_OUTPUT vs_main( in VS_INPUT In )
{
VS_OUTPUT Out=(VS_OUTPUT)0; //create an output vertex
Out.Position = mul(In.Position, WorldViewProj); //apply vertex transformation
Out.Texture = In.Texture;
Out.Texture_zw = float2(In.Texture.z, In.Texture.w);
Out.Color = In.Color;
//Out.Psize = In.Psize;
Out.Psize=(Out.Position.z)*10.0;
return Out; //return output vertex
}
float4 PS_Particle_main(float2 vPos: TEXCOORD0, float2 text_zw: TEXCOORD1) : COLOR
{
vPos.x*=offset_x;
vPos.y*=offset_y;
vPos += float2(text_zw[0], text_zw[1]);
return tex2D(s_2D, vPos);
}
technique RenderVS
{
pass p0
{
AlphaBlendEnable = true;
AlphaTestEnable = false;
SrcBlend = SRCALPHA;
DestBlend = INVSRCALPHA;
POINTSPRITEENABLE = true;
POINTSCALEENABLE = true;
POINTSIZE_MIN = 1.0f;
POINTSIZE_MAX = 400.0f;
POINTSCALE_A = 1.0f;
POINTSCALE_B = 1.0f;
POINTSCALE_C = 1.0f;
ZWRITEENABLE = false;
Sampler[0] = (S0);
VertexShader = compile vs_1_1 vs_main();
PixelShader = compile ps_2_0 PS_Particle_main();
}
}
I had the same problem for a while and it costed me a lot of time. I have not found any documentation about this problematic, but with testing on ATI and NVIDIA devices I found the difference. With pointsprites ATI works all fine, it interpolates the texturecoordinates properly into TEXCOORD0. In contrast NVIDIA does nearly the same, but they write the texturecoordinates in all fields with a TEXCOORD-interpolator. So all information which you pass by texturecoordinates to the pixelshader will be overwritten. I solved this by using a COLOR-interpolator instead of a TEXCOORD-interpolator. Very strange, but it works fine for me :) In your case it would be:
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COLOR0;
float2 Texture : TEXCOORD0;
float2 Texture_zw : COLOR1;
float1 Psize : PSIZE;
};

DX10 Skybox Shader

I'm trying to write a skybox shader in DX10 using the following HLSL code:
//////////////////////////////////////////////////////////////////////////
// world matrix for each rendered object
float4x4 g_mWorld;
// single cubemap texture
Texture2D g_tCubeMap;
// basic mirror texture sampler
SamplerState g_sSamplerMirror
{
Filter = MIN_MAG_MIP_POINT;
AddressU = MIRROR;
AddressV = MIRROR;
};
//////////////////////////////////////////////////////////////////////////
// pre-defined vertex formats for vertex input layouts
struct VS_INPUT
{
float3 Position : POSITION;
};
struct PS_INPUT
{
float4 SPosition : SV_POSITION;
float3 UV : TEXCOORD;
};
//////////////////////////////////////////////////////////////////////////
PS_INPUT VS_Default( VS_INPUT Input )
{
PS_INPUT Output = (PS_INPUT)0;
Output.SPosition = float4(Input.Position,1.0f);
Output.UV = normalize( mul( Output.SPosition, g_mWorld ) ).xyz;
return Output;
}
//////////////////////////////////////////////////////////////////////////
float4 PS_Default( PS_INPUT Input ) : SV_TARGET0
{
return float4( texCUBE( g_sSamplerMirror, Input.UV ) );
}
//////////////////////////////////////////////////////////////////////////
technique10 TECH_Default
{
pass
{
SetVertexShader( CompileShader( vs_4_0, VS_Default() ) );
SetPixelShader( CompileShader( ps_4_0, PS_Default() ) );
SetGeometryShader( 0 );
}
}
Which gives the error "DX-9 style intrinsics are disabled when not in dx9 compatibility mode." on line 46:
return float4( texCUBE( g_sSamplerMirror, Input.UV ) );
Is there an alternative to texCUBE? How can I fix this without enabling dx9 compatibility mode?
Since you are using Shader Model 4 you should be able to create a TextureCube object and then call the Sample method.

Resources