<p>So, I figured it out.</p>

<p>While UAV will be necessary when I start manipulating data in Compute Shaders, for the time being, SRV works fine provided the resource is read-only from the fragment shader.</p>

<p>The two big problems were</p>

<ol>
<li><p>Creating an ImageTexture that was receiving the data. Note that the data copy was occurring just fine, but the texture was never used in the rest of the code. The correct place was to copy the code into the resource within m_WindowQuad.</p></li>
<li><p>Creating the ImageTexture (later m_WindowQuad) resource as</p></li>
</ol>

<p><code>D3D12_RESOURCE_STATE_COPY_DEST</code></p>

<p>when it should have been defined as</p>

<p><code>D3D12_RESOURCE_STATE_COMMON</code></p>

<p>Near as I can tell, those two were the bulk of the problems.
The code rewritten, now functional:</p>

<pre><code>m_windowQuad.Initialize(m_D3dDevice, m_CommandList);

D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = {};
HeapDesc.NumDescriptors = 1;
HeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
HeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
ThrowIfFailed(m_D3dDevice-&gt;CreateDescriptorHeap(&amp;HeapDesc, IID_PPV_ARGS(&amp;m_DescriptorHeap)));

// Fill heap with actual descriptor
CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(
    m_DescriptorHeap-&gt;GetCPUDescriptorHandleForHeapStart());

// texture data
const uint width = 16;
const uint pitch = 16 * sizeof(u8) * 4;
const uint height = 16;
char colors[width * height * 4];
DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
for (int i = 0; i &lt; height*width * 4; i++)
    colors[i] = i % 256;

D3D12_RESOURCE_DESC texDesc = {};
texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
texDesc.Width = width;
texDesc.Height = height;
texDesc.DepthOrArraySize = 1;
texDesc.MipLevels = 1;
texDesc.Format = format;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;

D3D12_SUBRESOURCE_DATA texResource;
texResource.pData = colors;
texResource.RowPitch = pitch;
texResource.SlicePitch = texResource.RowPitch * height;


ThrowIfFailed(m_D3dDevice-&gt;CreateCommittedResource(
    &amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
    D3D12_HEAP_FLAG_NONE, 
    &amp;texDesc,
    D3D12_RESOURCE_STATE_COMMON,
    nullptr, 
    IID_PPV_ARGS(m_windowQuad.Texture.ReleaseAndGetAddressOf())));
m_windowQuad.Texture-&gt;SetName(L"Window Texture");

ThrowIfFailed(m_D3dDevice-&gt;CreateCommittedResource(
    &amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
    D3D12_HEAP_FLAG_NONE,
    &amp;CD3DX12_RESOURCE_DESC::Buffer(texResource.SlicePitch * 16),
    D3D12_RESOURCE_STATE_GENERIC_READ,
    nullptr,
    IID_PPV_ARGS(m_windowQuad.TextureUploader.ReleaseAndGetAddressOf())));
m_windowQuad.TextureUploader-&gt;SetName(L"Window Texture Uploader");

D3D12_SHADER_RESOURCE_VIEW_DESC SrvDesc = { };
SrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
SrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
SrvDesc.Texture2D.MostDetailedMip = 0;
SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
SrvDesc.Format = m_windowQuad.Texture-&gt;GetDesc().Format;
SrvDesc.Texture2D.MipLevels = m_windowQuad.Texture-&gt;GetDesc().MipLevels;
SrvDesc.Texture2D.MostDetailedMip = 0;
SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;

m_CommandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(m_windowQuad.Texture.Get(),
    D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));
UpdateSubresources(m_CommandList.Get(), m_windowQuad.Texture.Get(), m_windowQuad.TextureUploader.Get(), 0, 0, 1, &amp;texResource);
m_CommandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(m_windowQuad.Texture.Get(),
    D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));

m_D3dDevice-&gt;CreateShaderResourceView(m_windowQuad.Texture.Get(), &amp;SrvDesc, hDescriptor);
</code></pre>

CC BY-SA 4.0
2018-11-26T17:04:58.103Z
2018-11-26T17:04:58.103Z
Trevor Black
<p>Resource Views are read-only in DirectX. Have you tried using an unordered-access view instead?</p>

<p>The CPU-side setup for these is similar to standard resource views (at least in DX11, I haven't used DX12), just with more detail and slightly different objects:</p>

<p><a href="https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_unordered_access_view_desc" rel="nofollow noreferrer">https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_unordered_access_view_desc</a></p>

<p><a href="https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createunorderedaccessview" rel="nofollow noreferrer">https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createunorderedaccessview</a></p>

<p>On the GPU side:</p>

<p>I can't see your shader, but I assume you've declared something like</p>

<p><code>Texture2D&lt;float4&gt; tex : register(t0)</code></p>

<p>If so you'll need to change the binding for <code>tex</code> into a write-allowed unordered-access texture, which would be:</p>

<p><code>RWTexture2D&lt;float4&gt; tex : register(u0)</code> </p>

CC BY-SA 4.0
2018-11-26T08:42:56.740Z
2018-11-26T10:34:11.823Z
2018-11-26T10:34:11.823Z
Paul Ferris
<p>I'm hoping to port my existing toy raytracer to a window so that I can see samples accumulate over time. And then port over to Pixar's pmj02:
<a href="https://graphics.pixar.com/library/ProgressiveMultiJitteredSampling/paper.pdf" rel="nofollow noreferrer">https://graphics.pixar.com/library/ProgressiveMultiJitteredSampling/paper.pdf</a></p>

<p>I'm working within DX12 because the idea is to begin porting elements of the raytracer slowly into DX compute (or DXR), which I'm already familiar with.</p>

<p>I have a simple quad fragment shader that samples a single Texture2D and writes to a quad on screen. At the moment, I am only writing data on startup, so that I can prove that copying over arbitrary 2D data to a texture2D is possible. However, I can only seem to write a black quad. I've flipped the sampler in hlsl with</p>

<pre><code>return 1.0f - g_WindowTexture.Sample(g_SamLinearWrap, pin.TexCoordF) 
</code></pre>

<p>and the quad went white, so the texture definitely has zeros for data. This leads me to believe that I'm not correctly copying data over to the GPU resource.</p>

<p>The window build code:</p>

<pre><code>m_windowQuad.Initialize(m_D3dDevice, m_CommandList);

D3D12_DESCRIPTOR_HEAP_DESC SrvHeapDesc = {};
SrvHeapDesc.NumDescriptors = 1;
SrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
SrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
ThrowIfFailed(m_D3dDevice-&gt;CreateDescriptorHeap(&amp;SrvHeapDesc, IID_PPV_ARGS(&amp;m_SrvDescriptorHeap)));

// Fill heap with actual descriptor
CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(
    m_SrvDescriptorHeap-&gt;GetCPUDescriptorHandleForHeapStart());

// Load initial texture
auto texture = std::make_unique&lt;ImageTexture&gt;();
// texture data
const uint width = 16;
const uint pitch = 16 * sizeof(u8) * 4;
const uint height = 16;
char colors[width * height * 4];
DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
for (int i = 0; i &lt; height*width * 4; i++)
    colors[i] = i % 256;

D3D12_RESOURCE_DESC texDesc = {};
texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
texDesc.Width = width;
texDesc.Height = height;
texDesc.DepthOrArraySize = 1;
texDesc.MipLevels = 1;
texDesc.Format = format;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Flags = D3D12_RESOURCE_FLAG_NONE;

CD3DX12_HEAP_PROPERTIES HeapProperties(D3D12_HEAP_TYPE_DEFAULT);

ThrowIfFailed(m_D3dDevice-&gt;CreateCommittedResource(&amp;HeapProperties, D3D12_HEAP_FLAG_NONE, &amp;texDesc, 
    D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(texture-&gt;Resource.ReleaseAndGetAddressOf())));

D3D12_SUBRESOURCE_DATA texResource;
texResource.pData = colors;
texResource.RowPitch = (pitch + (D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1)) &amp; ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1);
texResource.SlicePitch = texResource.RowPitch * height;

D3D12_SHADER_RESOURCE_VIEW_DESC SrvDesc = { };
SrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
SrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
SrvDesc.Texture2D.MostDetailedMip = 0;
SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
SrvDesc.Format = texture-&gt;Resource-&gt;GetDesc().Format;
SrvDesc.Texture2D.MipLevels = texture-&gt;Resource-&gt;GetDesc().MipLevels;
SrvDesc.Texture2D.MostDetailedMip = 0;
SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;

Microsoft::WRL::ComPtr&lt;ID3D12Resource&gt; IntResource;
ThrowIfFailed(m_D3dDevice-&gt;CreateCommittedResource(
    &amp;CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
    D3D12_HEAP_FLAG_NONE,
    &amp;CD3DX12_RESOURCE_DESC::Buffer(texResource.SlicePitch * 16),
    D3D12_RESOURCE_STATE_GENERIC_READ,
    nullptr,
    IID_PPV_ARGS(IntResource.ReleaseAndGetAddressOf())));

m_CommandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(texture-&gt;Resource.Get(),
    D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));
UpdateSubresources(m_CommandList.Get(), texture-&gt;Resource.Get(), IntResource.Get(), 0, 0, 1, &amp;texResource);
m_CommandList-&gt;ResourceBarrier(1, &amp;CD3DX12_RESOURCE_BARRIER::Transition(texture-&gt;Resource.Get(),
    D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));

m_D3dDevice-&gt;CreateShaderResourceView(texture-&gt;Resource.Get(), &amp;SrvDesc, hDescriptor);
texture-&gt;SRVHeapIndex = 0;
m_Textures["quad"] = std::move(texture);
</code></pre>

<p>And then per frame the following draw calls are made:</p>

<pre><code>void PBRApp::DrawWindowQuad(ID3D12GraphicsCommandList* cmdList)
{
    cmdList-&gt;IASetVertexBuffers(0, 1, &amp;m_windowQuad.VertexBufferView());
    cmdList-&gt;IASetIndexBuffer(&amp;m_windowQuad.IndexBufferView());
    cmdList-&gt;IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    CD3DX12_GPU_DESCRIPTOR_HANDLE Tex(m_SrvDescriptorHeap-&gt;GetGPUDescriptorHandleForHeapStart());
    Tex.Offset(0, m_cbvSrvDescriptorSize);

    cmdList-&gt;SetGraphicsRootDescriptorTable(0, Tex);
    cmdList-&gt;DrawIndexedInstanced(m_windowQuad.IndexCount, 1, 
        m_windowQuad.StartIndexLocation, m_windowQuad.BaseVertexLocation, 0);
}
</code></pre>

<p>So, I'm fairly confident in my root signature, PSO, and draw calls.
But I can't figure out why I keep getting a black quad (possibly empty data) drawn to the screen.</p>

<p>Am I just going about this the wrong way?</p>

<raytracing><fragment-shader><directx12>
Writing data to a shader resource at runtime in DX12
Trevor Black
# Writing data to a shader resource at runtime in DX12

(Asked by: username_0 on 2018-11-25)

I'm hoping to port my existing toy raytracer to a window so that I can see samples accumulate over time. And then port over to Pixar's pmj02:
<https://graphics.pixar.com/library/ProgressiveMultiJitteredSampling/paper.pdf>

I'm working within DX12 because the idea is to begin porting elements of the raytracer slowly into DX compute (or DXR), which I'm already familiar with.

I have a simple quad fragment shader that samples a single Texture2D and writes to a quad on screen. At the moment, I am only writing data on startup, so that I can prove that copying over arbitrary 2D data to a texture2D is possible. However, I can only seem to write a username_0 quad. I've flipped the sampler in hlsl with

```
return 1.0f - g_WindowTexture.Sample(g_SamLinearWrap, pin.TexCoordF) 

```

and the quad went white, so the texture definitely has zeros for data. This leads me to believe that I'm not correctly copying data over to the GPU resource.

The window build code:

```
m_windowQuad.Initialize(m_D3dDevice, m_CommandList);

D3D12_DESCRIPTOR_HEAP_DESC SrvHeapDesc = {};
SrvHeapDesc.NumDescriptors = 1;
SrvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
SrvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
ThrowIfFailed(m_D3dDevice->CreateDescriptorHeap(&SrvHeapDesc, IID_PPV_ARGS(&m_SrvDescriptorHeap)));

// Fill heap with actual descriptor
CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(
    m_SrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());

// Load initial texture
auto texture = std::make_unique<ImageTexture>();
// texture data
const uint width = 16;
const uint pitch = 16 * sizeof(u8) * 4;
const uint height = 16;
char colors[width * height * 4];
DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
for (int i = 0; i < height*width * 4; i++)
    colors[i] = i % 256;

D3D12_RESOURCE_DESC texDesc = {};
texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
texDesc.Width = width;
texDesc.Height = height;
texDesc.DepthOrArraySize = 1;
texDesc.MipLevels = 1;
texDesc.Format = format;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Flags = D3D12_RESOURCE_FLAG_NONE;

CD3DX12_HEAP_PROPERTIES HeapProperties(D3D12_HEAP_TYPE_DEFAULT);

ThrowIfFailed(m_D3dDevice->CreateCommittedResource(&HeapProperties, D3D12_HEAP_FLAG_NONE, &texDesc, 
    D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(texture->Resource.ReleaseAndGetAddressOf())));

D3D12_SUBRESOURCE_DATA texResource;
texResource.pData = colors;
texResource.RowPitch = (pitch + (D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1)) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1);
texResource.SlicePitch = texResource.RowPitch * height;

D3D12_SHADER_RESOURCE_VIEW_DESC SrvDesc = { };
SrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
SrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
SrvDesc.Texture2D.MostDetailedMip = 0;
SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
SrvDesc.Format = texture->Resource->GetDesc().Format;
SrvDesc.Texture2D.MipLevels = texture->Resource->GetDesc().MipLevels;
SrvDesc.Texture2D.MostDetailedMip = 0;
SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;

Microsoft::WRL::ComPtr<ID3D12Resource> IntResource;
ThrowIfFailed(m_D3dDevice->CreateCommittedResource(
    &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
    D3D12_HEAP_FLAG_NONE,
    &CD3DX12_RESOURCE_DESC::Buffer(texResource.SlicePitch * 16),
    D3D12_RESOURCE_STATE_GENERIC_READ,
    nullptr,
    IID_PPV_ARGS(IntResource.ReleaseAndGetAddressOf())));

m_CommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(texture->Resource.Get(),
    D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));
UpdateSubresources(m_CommandList.Get(), texture->Resource.Get(), IntResource.Get(), 0, 0, 1, &texResource);
m_CommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(texture->Resource.Get(),
    D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));

m_D3dDevice->CreateShaderResourceView(texture->Resource.Get(), &SrvDesc, hDescriptor);
texture->SRVHeapIndex = 0;
m_Textures["quad"] = std::move(texture);

```

And then per frame the following draw calls are made:

```
void PBRApp::DrawWindowQuad(ID3D12GraphicsCommandList* cmdList)
{
    cmdList->IASetVertexBuffers(0, 1, &m_windowQuad.VertexBufferView());
    cmdList->IASetIndexBuffer(&m_windowQuad.IndexBufferView());
    cmdList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    CD3DX12_GPU_DESCRIPTOR_HANDLE Tex(m_SrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
    Tex.Offset(0, m_cbvSrvDescriptorSize);

    cmdList->SetGraphicsRootDescriptorTable(0, Tex);
    cmdList->DrawIndexedInstanced(m_windowQuad.IndexCount, 1, 
        m_windowQuad.StartIndexLocation, m_windowQuad.BaseVertexLocation, 0);
}

```

So, I'm fairly confident in my root signature, PSO, and draw calls.
But I can't figure out why I keep getting a username_0 quad (possibly empty data) drawn to the screen.

Am I just going about this the wrong way?

**Tags:** raytracing, fragment-shader, directx12


---

## 2 answers

### Answer by username_0 on 2018-11-26. Score: 1

So, I figured it out.

While UAV will be necessary when I start manipulating data in Compute Shaders, for the time being, SRV works fine provided the resource is read-only from the fragment shader.

The two big problems were

1. Creating an ImageTexture that was receiving the data. Note that the data copy was occurring just fine, but the texture was never used in the rest of the code. The correct place was to copy the code into the resource within m\_WindowQuad.
2. Creating the ImageTexture (later m\_WindowQuad) resource as

`D3D12_RESOURCE_STATE_COPY_DEST`

when it should have been defined as

`D3D12_RESOURCE_STATE_COMMON`

Near as I can tell, those two were the bulk of the problems.
The code rewritten, now functional:

```
m_windowQuad.Initialize(m_D3dDevice, m_CommandList);

D3D12_DESCRIPTOR_HEAP_DESC HeapDesc = {};
HeapDesc.NumDescriptors = 1;
HeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
HeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
ThrowIfFailed(m_D3dDevice->CreateDescriptorHeap(&HeapDesc, IID_PPV_ARGS(&m_DescriptorHeap)));

// Fill heap with actual descriptor
CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(
    m_DescriptorHeap->GetCPUDescriptorHandleForHeapStart());

// texture data
const uint width = 16;
const uint pitch = 16 * sizeof(u8) * 4;
const uint height = 16;
char colors[width * height * 4];
DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
for (int i = 0; i < height*width * 4; i++)
    colors[i] = i % 256;

D3D12_RESOURCE_DESC texDesc = {};
texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
texDesc.Width = width;
texDesc.Height = height;
texDesc.DepthOrArraySize = 1;
texDesc.MipLevels = 1;
texDesc.Format = format;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;

D3D12_SUBRESOURCE_DATA texResource;
texResource.pData = colors;
texResource.RowPitch = pitch;
texResource.SlicePitch = texResource.RowPitch * height;

ThrowIfFailed(m_D3dDevice->CreateCommittedResource(
    &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
    D3D12_HEAP_FLAG_NONE, 
    &texDesc,
    D3D12_RESOURCE_STATE_COMMON,
    nullptr, 
    IID_PPV_ARGS(m_windowQuad.Texture.ReleaseAndGetAddressOf())));
m_windowQuad.Texture->SetName(L"Window Texture");

ThrowIfFailed(m_D3dDevice->CreateCommittedResource(
    &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
    D3D12_HEAP_FLAG_NONE,
    &CD3DX12_RESOURCE_DESC::Buffer(texResource.SlicePitch * 16),
    D3D12_RESOURCE_STATE_GENERIC_READ,
    nullptr,
    IID_PPV_ARGS(m_windowQuad.TextureUploader.ReleaseAndGetAddressOf())));
m_windowQuad.TextureUploader->SetName(L"Window Texture Uploader");

D3D12_SHADER_RESOURCE_VIEW_DESC SrvDesc = { };
SrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
SrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
SrvDesc.Texture2D.MostDetailedMip = 0;
SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
SrvDesc.Format = m_windowQuad.Texture->GetDesc().Format;
SrvDesc.Texture2D.MipLevels = m_windowQuad.Texture->GetDesc().MipLevels;
SrvDesc.Texture2D.MostDetailedMip = 0;
SrvDesc.Texture2D.ResourceMinLODClamp = 0.0f;

m_CommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_windowQuad.Texture.Get(),
    D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_DEST));
UpdateSubresources(m_CommandList.Get(), m_windowQuad.Texture.Get(), m_windowQuad.TextureUploader.Get(), 0, 0, 1, &texResource);
m_CommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_windowQuad.Texture.Get(),
    D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));

m_D3dDevice->CreateShaderResourceView(m_windowQuad.Texture.Get(), &SrvDesc, hDescriptor);

```


---

### Answer by username_1 on 2018-11-26. Score: 0

Resource Views are read-only in DirectX. Have you tried using an unordered-access view instead?

The CPU-side setup for these is similar to standard resource views (at least in DX11, I haven't used DX12), just with more detail and slightly different objects:

<https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_unordered_access_view_desc>

<https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12device-createunorderedaccessview>

On the GPU side:

I can't see your shader, but I assume you've declared something like

`Texture2D<float4> tex : register(t0)`

If so you'll need to change the binding for `tex` into a write-allowed unordered-access texture, which would be:

`RWTexture2D<float4> tex : register(u0)`


---

