d3d11u.h revision 92617aeac109481258f0c3863d09c1b8903d438b
1/**************************************************************************
2 *
3 * Copyright 2010 Luca Barbieri
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27#include <vector>
28
29#include "d3d11blit.hlsl.ps.h"
30#include "d3d11blit.hlsl.vs.h"
31
32template<typename index_type = unsigned>
33struct triangle_list_indices : public std::vector<index_type>
34{
35	unsigned base;
36	bool flip;
37
38	triangle_list_indices()
39	: base(0), flip(false)
40	{}
41
42	void poly(unsigned a, unsigned b, unsigned c)
43	{
44		this->push_back(base + a);
45		this->push_back(base + (flip ? c : b));
46		this->push_back(base + (flip ? b : c));
47	}
48
49	void poly(unsigned a, unsigned b, unsigned c, unsigned d)
50	{
51		poly(a, b, c);
52		poly(a, c, d);
53	}
54
55	void poly(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e)
56	{
57		poly(a, b, c, d);
58		poly(a, d, e);
59	}
60
61	void poly(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f)
62	{
63		poly(a, b, c, d, e);
64		poly(a, e, f);
65	}
66
67	void poly(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f, unsigned g)
68	{
69		poly(a, b, c, d, e, f);
70		poly(a, f, g);
71	}
72
73	void poly(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f, unsigned g, unsigned h)
74	{
75		poly(a, b, c, d, e, f, g);
76		poly(a, g, h);
77	}
78};
79
80struct mesh
81{
82	ID3D11InputLayout* layout;
83	ID3D11Buffer* buffer;
84	D3D11_PRIMITIVE_TOPOLOGY topology;
85	unsigned vertex_size;
86	unsigned draw_count;
87	DXGI_FORMAT index_format;
88	unsigned index_offset;
89
90	mesh(ID3D11Device* dev, D3D11_PRIMITIVE_TOPOLOGY topology,
91		const D3D11_INPUT_ELEMENT_DESC *elements, unsigned num_elements,
92		const void* vs, unsigned vs_size,
93		const void* vertices, unsigned vertex_size, unsigned num_vertices,
94		const void* indices = 0, unsigned index_size = 0, unsigned num_indices = 0)
95		: topology(topology), vertex_size(vertex_size), draw_count(index_size ? num_indices : num_vertices)
96	{
97		dev->CreateInputLayout(elements, num_elements, vs, vs_size, &layout);
98		if(index_size == 2)
99			index_format = DXGI_FORMAT_R16_UINT;
100		else if(index_size == 4)
101			index_format = DXGI_FORMAT_R32_UINT;
102		else
103			index_format = DXGI_FORMAT_UNKNOWN;
104		this->vertex_size = vertex_size;
105		index_offset = vertex_size * num_vertices;
106
107	   	D3D11_BUFFER_DESC bufferd;
108		memset(&bufferd, 0, sizeof(bufferd));
109		bufferd.Usage = D3D11_USAGE_IMMUTABLE;
110		bufferd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
111		if(index_format)
112			bufferd.BindFlags |= D3D11_BIND_INDEX_BUFFER;
113		bufferd.ByteWidth = index_offset + index_format * num_indices;
114
115		char* data = (char*)malloc(bufferd.ByteWidth);
116		memcpy(data, vertices, vertex_size * num_vertices);
117		memcpy(data + index_offset, indices, index_size * num_indices);
118
119		D3D11_SUBRESOURCE_DATA buffersd;
120		buffersd.pSysMem = data;
121
122		ensure(dev->CreateBuffer(&bufferd, &buffersd, &buffer));
123		free(data);
124	}
125
126	~mesh()
127	{
128		layout->Release();
129		buffer->Release();
130	}
131
132	void bind(ID3D11DeviceContext* ctx)
133	{
134		unsigned offset = 0;
135		ctx->IASetPrimitiveTopology(topology);
136		ctx->IASetInputLayout(layout);
137		if(index_format)
138			ctx->IASetIndexBuffer(buffer, index_format, index_offset);
139		ctx->IASetVertexBuffers(0, 1, &buffer, &vertex_size, &offset);
140	}
141
142	void draw_bound(ID3D11DeviceContext* ctx)
143	{
144		if(index_format)
145			ctx->DrawIndexed(draw_count, 0, 0);
146		else
147			ctx->Draw(draw_count, 0);
148	}
149
150	void bind_and_draw(ID3D11DeviceContext* ctx)
151	{
152		bind(ctx);
153		draw_bound(ctx);
154	}
155};
156
157mesh* create_tex_quad(ID3D11Device* dev, const BYTE* vs, unsigned vs_size)
158{
159	float quad_data[] = {
160		-1, -1, 0, 1,
161		-1, 1, 0, 0,
162		1, -1, 1, 1,
163		1, 1, 1, 0,
164	};
165
166	D3D11_INPUT_ELEMENT_DESC elements[2] =
167	{
168		{"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
169		{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
170	};
171
172	return new mesh(dev, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP,
173		elements, 2,
174		vs, vs_size,
175		quad_data, 4 * sizeof(float), 4,
176		0, 0, 0);
177}
178
179struct d3d11_blitter
180{
181	mesh* quad;
182	ID3D11VertexShader* vs;
183	ID3D11PixelShader* ps;
184	ID3D11SamplerState* sampler[2];
185
186	d3d11_blitter(ID3D11Device* dev)
187	{
188		quad = create_tex_quad(dev, g_vs_blit, sizeof(g_vs_blit));
189
190		dev->CreateVertexShader(g_vs_blit, sizeof(g_vs_blit), 0, &vs);
191		dev->CreatePixelShader(g_ps_blit, sizeof(g_ps_blit), 0, &ps);
192
193		for(unsigned i = 0; i < 2; ++i)
194		{
195			D3D11_SAMPLER_DESC samplerd;
196			memset(&samplerd, 0, sizeof(samplerd));
197			samplerd.Filter = i ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_LINEAR;
198			samplerd.AddressU = samplerd.AddressV = samplerd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
199			dev->CreateSamplerState(&samplerd, &sampler[i]);
200		}
201	}
202
203	void bind(ID3D11DeviceContext* ctx, ID3D11ShaderResourceView* srv, ID3D11RenderTargetView* rtv, float x, float y, float width, float height, bool linear)
204	{
205		D3D11_VIEWPORT vp;
206		vp.TopLeftX = x;
207		vp.TopLeftY = y;
208		vp.Width = width;
209		vp.Height = height;
210		vp.MinDepth = 0;
211		vp.MaxDepth = 1;
212		ctx->RSSetViewports(1, &vp);
213		ctx->RSSetState(0);
214		ctx->OMSetBlendState(0, 0, ~0);
215		ctx->OMSetDepthStencilState(0, 0);
216		ctx->OMSetRenderTargets(1, &rtv, 0);
217		ctx->VSSetShader(vs, 0, 0);
218		ctx->PSSetShader(ps, 0, 0);
219		ctx->PSSetShaderResources(0, 1, &srv);
220		ctx->PSSetSamplers(0, 1, &sampler[!!linear]);
221		quad->bind(ctx);
222	}
223
224	void draw_bound(ID3D11DeviceContext* ctx)
225	{
226		quad->draw_bound(ctx);
227	}
228
229	void bind_draw_and_unbind(ID3D11DeviceContext* ctx, ID3D11ShaderResourceView* srv, ID3D11RenderTargetView* rtv, float x, float y, float width, float height, bool linear)
230	{
231		bind(ctx, srv, rtv, x, y, width, height, linear);
232		draw_bound(ctx);
233		unbind(ctx);
234	}
235
236	void unbind(ID3D11DeviceContext* ctx)
237	{
238		void* null = 0;
239		ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&null);
240		ctx->PSSetSamplers(0, 1, (ID3D11SamplerState**)&null);
241	}
242};
243
244template<typename T, unsigned n>
245struct vec_t
246{
247	T v[n];
248
249	T& operator [](unsigned i)
250	{
251		return v[i];
252	}
253
254	const T& operator [](unsigned i) const
255	{
256		return v[i];
257	}
258};
259
260template<typename T, unsigned n>
261vec_t<T, n> operator -(const vec_t<T, n> a)
262{
263	vec_t<T, n> r;
264	for(unsigned i = 0; i < n; ++i)
265		r[i] = -a[i];
266	return r;
267}
268
269template<typename T, unsigned n>
270vec_t<T, n> operator +(const vec_t<T, n>& a, const vec_t<T, n>& b)
271{
272	vec_t<T, n> r;
273	for(unsigned i = 0; i < n; ++i)
274		r[i] = a[i] + b[i];
275	return r;
276}
277
278template<typename T, unsigned n>
279vec_t<T, n>& operator +=(vec_t<T, n>& a, const vec_t<T, n>& b)
280{
281	for(unsigned i = 0; i < n; ++i)
282		a[i] += b[i];
283	return a;
284}
285
286template<typename T, unsigned r, unsigned c>
287struct mat_t : public vec_t<vec_t<T, r>, c>
288{};
289
290template<typename T, unsigned n>
291vec_t<T, n> operator *(const vec_t<T, n>& a, const T& b)
292{
293	vec_t<T, n> r;
294	for(unsigned i = 0; i < n; ++i)
295		r[i] = a[i] * b;
296	return r;
297}
298
299template<typename T, unsigned n>
300vec_t<T, n> operator *(const T& b, const vec_t<T, n>& a)
301{
302	vec_t<T, n> r;
303	for(unsigned i = 0; i < n; ++i)
304		r[i] = a[i] * b;
305	return r;
306}
307
308template<typename T, unsigned d, unsigned e>
309vec_t<T, e> operator *(const mat_t<T, e, d>& m, const vec_t<T, d>& b)
310{
311	vec_t<T, e> r;
312	r = m[0] * b[0];
313	for(unsigned i = 1; i < d; ++i)
314		r += m[i] * b[i];
315	return r;
316}
317
318template<typename T, unsigned d, unsigned e, unsigned f>
319mat_t<T, e, f> operator *(const mat_t<T, e, d>& m, const mat_t<T, d, f>& b)
320{
321	mat_t<T, e, f> r;
322	for(unsigned i = 0; i < d; ++i)
323		r[i] = m * b[i];
324	return r;
325}
326
327template<typename T>
328vec_t<T, 3> vec(T a, T b, T c)
329{
330	vec_t<T, 4> v;
331	v[0] = a;
332	v[1] = b;
333	v[2] = c;
334	return v;
335}
336
337template<typename T>
338vec_t<T, 4> vec(T a, T b, T c, T d)
339{
340	vec_t<T, 4> v;
341	v[0] = a;
342	v[1] = b;
343	v[2] = c;
344	v[3] = d;
345	return v;
346}
347
348typedef mat_t<float, 4, 4> float4x4;
349typedef mat_t<float, 4, 3> float4x3;
350typedef mat_t<float, 3, 4> float3x4;
351typedef mat_t<float, 3, 3> float3x3;
352
353typedef vec_t<float, 3> float3;
354typedef vec_t<float, 4> float4;
355
356template<typename T>
357mat_t<T, 4, 4> mat4x4_frustum(T left, T right, T bottom, T top, T nearval, T farval)
358{
359	T x = (2.0f * nearval) / (right - left);
360	T y = (2.0f * nearval) / (top - bottom);
361	T a = (right + left) / (right - left);
362	T b = (top + bottom) / (top - bottom);
363	T c = -(farval + nearval) / (farval - nearval);
364	T d = -(2.0f * farval * nearval) / (farval - nearval);
365	T _0 = (T)0;
366
367	mat_t<T, 4, 4> m;
368	m[0] = vec(x, _0, _0, _0);
369	m[1] = vec(_0, y, _0, _0);
370	m[2] = vec(a, b, c, (T)-1);
371	m[3] = vec(_0, _0, d, _0);
372	return m;
373}
374
375template<typename T>
376mat_t<T, 3, 3> mat3x3_diag(T v)
377{
378	mat_t<T, 3, 3> m;
379	T _0 = (T)0;
380	m[0] = vec(v, _0, _0);
381	m[1] = vec(_0, v, _0);
382	m[2] = vec(_0, _0, v);
383	return m;
384}
385
386template<typename T>
387mat_t<T, 4, 4> mat4x4_diag(T v)
388{
389	mat_t<T, 4, 4> m;
390	T _0 = (T)0;
391	m[0] = vec(v, _0, _0, _0);
392	m[1] = vec(_0, v, _0, _0);
393	m[2] = vec(_0, _0, v, _0);
394	m[3] = vec(_0, _0, _0, v);
395	return m;
396}
397
398template<typename T, unsigned n>
399mat_t<T, n, n> mat_push_rotate(const mat_t<T, n, n>& m, unsigned axis, T angle)
400{
401	T s = (T)sin(angle);
402	T c = (T)cos(angle);
403
404	mat_t<T, n, n> r = m;
405	unsigned a = (axis + 1) % 3;
406	unsigned b = (axis + 2) % 3;
407	r[a] = (m[a] * c) + (m[b] * s);
408	r[b] = -(m[a] * s) + (m[b] * c);
409	return r;
410}
411
412template<typename T, unsigned n>
413mat_t<T, n, n> mat_push_translate(const mat_t<T, n, n>& m, float x, float y, float z)
414{
415	mat_t<T, n, n> r = m;
416	vec_t<T, n> v;
417	v[0] = x;
418	v[1] = y;
419	v[2] = z;
420	if(n >= 4)
421		v[3] = (T)0;
422	r[3] += m * v;
423	return r;
424}
425