Home | History | Annotate | Download | only in d3d11app
      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 
     32 template<typename index_type = unsigned>
     33 struct 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 
     80 struct 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 
    157 mesh* 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 
    179 struct 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 
    244 template<typename T, unsigned n>
    245 struct 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 
    260 template<typename T, unsigned n>
    261 vec_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 
    269 template<typename T, unsigned n>
    270 vec_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 
    278 template<typename T, unsigned n>
    279 vec_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 
    286 template<typename T, unsigned r, unsigned c>
    287 struct mat_t : public vec_t<vec_t<T, r>, c>
    288 {};
    289 
    290 template<typename T, unsigned n>
    291 vec_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 
    299 template<typename T, unsigned n>
    300 vec_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 
    308 template<typename T, unsigned d, unsigned e>
    309 vec_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 
    318 template<typename T, unsigned d, unsigned e, unsigned f>
    319 mat_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 
    327 template<typename T>
    328 vec_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 
    337 template<typename T>
    338 vec_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 
    348 typedef mat_t<float, 4, 4> float4x4;
    349 typedef mat_t<float, 4, 3> float4x3;
    350 typedef mat_t<float, 3, 4> float3x4;
    351 typedef mat_t<float, 3, 3> float3x3;
    352 
    353 typedef vec_t<float, 3> float3;
    354 typedef vec_t<float, 4> float4;
    355 
    356 template<typename T>
    357 mat_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 
    375 template<typename T>
    376 mat_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 
    386 template<typename T>
    387 mat_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 
    398 template<typename T, unsigned n>
    399 mat_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 
    412 template<typename T, unsigned n>
    413 mat_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