-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathRenderTexture.cpp
157 lines (124 loc) · 4.27 KB
/
RenderTexture.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//--------------------------------------------------------------------------------------
// File: RenderTexture.cpp
//
// Helper for managing offscreen render targets
//
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//-------------------------------------------------------------------------------------
#include "pch.h"
#include "RenderTexture.h"
#include "DirectXHelpers.h"
#include <algorithm>
#include <cstdio>
#include <stdexcept>
using namespace DirectX;
using namespace DX;
using Microsoft::WRL::ComPtr;
#ifdef __MINGW32__
#define DX_CONSTEXPR const
#else
#define DX_CONSTEXPR constexpr
#endif
RenderTexture::RenderTexture(DXGI_FORMAT format) noexcept :
m_state(D3D12_RESOURCE_STATE_COMMON),
m_srvDescriptor{},
m_rtvDescriptor{},
m_clearColor{},
m_format(format),
m_width(0),
m_height(0)
{
}
void RenderTexture::SetDevice(_In_ ID3D12Device* device,
D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor,
D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor)
{
if (device == m_device.Get()
&& srvDescriptor.ptr == m_srvDescriptor.ptr
&& rtvDescriptor.ptr == m_rtvDescriptor.ptr)
return;
if (m_device)
{
ReleaseDevice();
}
{
D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport = { m_format, D3D12_FORMAT_SUPPORT1_NONE, D3D12_FORMAT_SUPPORT2_NONE };
if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &formatSupport, sizeof(formatSupport))))
{
throw std::runtime_error("CheckFeatureSupport");
}
DX_CONSTEXPR UINT required = D3D12_FORMAT_SUPPORT1_TEXTURE2D | D3D12_FORMAT_SUPPORT1_RENDER_TARGET;
if ((formatSupport.Support1 & required) != required)
{
#ifdef _DEBUG
char buff[128] = {};
sprintf_s(buff, "RenderTexture: Device does not support the requested format (%u)!\n", m_format);
OutputDebugStringA(buff);
#endif
throw std::runtime_error("RenderTexture");
}
}
if (!srvDescriptor.ptr || !rtvDescriptor.ptr)
{
throw std::runtime_error("Invalid descriptors");
}
m_device = device;
m_srvDescriptor = srvDescriptor;
m_rtvDescriptor = rtvDescriptor;
}
void RenderTexture::SizeResources(size_t width, size_t height)
{
if (width == m_width && height == m_height)
return;
if (m_width > UINT32_MAX || m_height > UINT32_MAX)
{
throw std::out_of_range("Invalid width/height");
}
if (!m_device)
return;
m_width = m_height = 0;
auto const heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
const D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Tex2D(m_format,
static_cast<UINT64>(width),
static_cast<UINT>(height),
1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
D3D12_CLEAR_VALUE clearValue = { m_format, {} };
memcpy(clearValue.Color, m_clearColor, sizeof(clearValue.Color));
m_state = D3D12_RESOURCE_STATE_RENDER_TARGET;
// Create a render target
ThrowIfFailed(
m_device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES,
&desc,
m_state, &clearValue,
IID_GRAPHICS_PPV_ARGS(m_resource.ReleaseAndGetAddressOf()))
);
SetDebugObjectName(m_resource.Get(), L"RenderTexture RT");
// Create RTV.
m_device->CreateRenderTargetView(m_resource.Get(), nullptr, m_rtvDescriptor);
// Create SRV.
m_device->CreateShaderResourceView(m_resource.Get(), nullptr, m_srvDescriptor);
m_width = width;
m_height = height;
}
void RenderTexture::ReleaseDevice() noexcept
{
m_resource.Reset();
m_device.Reset();
m_state = D3D12_RESOURCE_STATE_COMMON;
m_width = m_height = 0;
m_srvDescriptor.ptr = m_rtvDescriptor.ptr = 0;
}
void RenderTexture::TransitionTo(_In_ ID3D12GraphicsCommandList* commandList,
D3D12_RESOURCE_STATES afterState)
{
TransitionResource(commandList, m_resource.Get(), m_state, afterState);
m_state = afterState;
}
void RenderTexture::SetWindow(const RECT& output)
{
// Determine the render target size in pixels.
auto const width = size_t(std::max<LONG>(output.right - output.left, 1));
auto const height = size_t(std::max<LONG>(output.bottom - output.top, 1));
SizeResources(width, height);
}