2021-11-26 17:08:41 +00:00
|
|
|
/*
|
|
|
|
Copyright 2021 flyinghead
|
|
|
|
|
|
|
|
This file is part of Flycast.
|
|
|
|
|
|
|
|
Flycast is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Flycast is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#pragma once
|
2021-11-29 17:22:25 +00:00
|
|
|
#include <d3d11.h>
|
2021-11-26 17:08:41 +00:00
|
|
|
#include "dx11_shaders.h"
|
|
|
|
|
|
|
|
class Quad
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
void init(const ComPtr<ID3D11Device>& device, ComPtr<ID3D11DeviceContext> deviceContext, DX11Shaders *shaders)
|
|
|
|
{
|
|
|
|
this->device = device;
|
|
|
|
this->deviceContext = deviceContext;
|
|
|
|
this->shaders = shaders;
|
|
|
|
|
|
|
|
vertexShader = shaders->getQuadVertexShader(false);
|
|
|
|
rotateVertexShader = shaders->getQuadVertexShader(true);
|
|
|
|
pixelShader = shaders->getQuadPixelShader();
|
|
|
|
|
|
|
|
// Input layout
|
|
|
|
D3D11_INPUT_ELEMENT_DESC layout[]
|
|
|
|
{
|
|
|
|
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
|
|
|
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 2 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
|
|
|
};
|
|
|
|
ComPtr<ID3DBlob> blob = shaders->getQuadVertexShaderBlob();
|
|
|
|
if (FAILED(device->CreateInputLayout(layout, ARRAY_SIZE(layout), blob->GetBufferPointer(), blob->GetBufferSize(), &inputLayout.get())))
|
|
|
|
WARN_LOG(RENDERER, "Input layout creation failed");
|
|
|
|
|
|
|
|
// Rasterizer state
|
|
|
|
{
|
|
|
|
D3D11_RASTERIZER_DESC desc{};
|
|
|
|
desc.FillMode = D3D11_FILL_SOLID;
|
|
|
|
desc.CullMode = D3D11_CULL_NONE;
|
|
|
|
desc.ScissorEnable = true;
|
|
|
|
desc.DepthClipEnable = true;
|
|
|
|
device->CreateRasterizerState(&desc, &rasterizerState.get());
|
|
|
|
}
|
|
|
|
// Depth-stencil state
|
|
|
|
{
|
|
|
|
D3D11_DEPTH_STENCIL_DESC desc{};
|
|
|
|
desc.DepthEnable = false;
|
|
|
|
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
|
|
|
desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
|
|
|
desc.StencilEnable = false;
|
|
|
|
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
|
|
|
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
|
|
desc.BackFace = desc.FrontFace;
|
|
|
|
device->CreateDepthStencilState(&desc, &depthStencilState.get());
|
|
|
|
}
|
|
|
|
// Vertex buffer
|
|
|
|
{
|
|
|
|
D3D11_BUFFER_DESC desc{};
|
|
|
|
desc.ByteWidth = sizeof(float) * 4 * 4;
|
|
|
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
|
|
|
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
|
|
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
|
|
|
device->CreateBuffer(&desc, nullptr, &vertexBuffer.get());
|
|
|
|
}
|
2021-11-29 17:22:25 +00:00
|
|
|
// Constant buffer
|
|
|
|
{
|
|
|
|
D3D11_BUFFER_DESC desc{};
|
|
|
|
desc.ByteWidth = sizeof(float) * 4;
|
|
|
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
|
|
|
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
|
|
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
|
|
|
device->CreateBuffer(&desc, nullptr, &constantBuffer.get());
|
|
|
|
}
|
2021-11-26 17:08:41 +00:00
|
|
|
}
|
|
|
|
|
2021-11-29 17:22:25 +00:00
|
|
|
void draw(ComPtr<ID3D11ShaderResourceView>& texView, ComPtr<ID3D11SamplerState> sampler, const float *color = nullptr,
|
|
|
|
float x = -1.f, float y = -1.f, float w = 2.f, float h = 2.f, bool rotate = false)
|
2021-11-26 17:08:41 +00:00
|
|
|
{
|
|
|
|
// Vertex buffer
|
|
|
|
Vertex vertices[4] {
|
|
|
|
{ x, y, 0.f, 1.f },
|
|
|
|
{ x, y + h, 0.f, 0.f },
|
|
|
|
{ x + w, y, 1.f, 1.f },
|
|
|
|
{ x + w, y + h, 1.f, 0.f },
|
|
|
|
};
|
|
|
|
D3D11_MAPPED_SUBRESOURCE mappedSubRes{};
|
|
|
|
deviceContext->Map(vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubRes);
|
|
|
|
memcpy(mappedSubRes.pData, vertices, sizeof(vertices));
|
|
|
|
deviceContext->Unmap(vertexBuffer, 0);
|
|
|
|
unsigned int stride = sizeof(Vertex);
|
|
|
|
unsigned int offset = 0;
|
|
|
|
deviceContext->IASetInputLayout(inputLayout);
|
|
|
|
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer.get(), &stride, &offset);
|
|
|
|
|
|
|
|
// Render states
|
|
|
|
deviceContext->OMSetDepthStencilState(depthStencilState, 0);
|
|
|
|
deviceContext->RSSetState(rasterizerState);
|
|
|
|
deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
|
|
|
deviceContext->VSSetShader(rotate ? rotateVertexShader : vertexShader, nullptr, 0);
|
|
|
|
deviceContext->PSSetShader(pixelShader, nullptr, 0);
|
|
|
|
|
|
|
|
// TODO Scissor?
|
|
|
|
//const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
|
|
|
|
//deviceContext->RSSetScissorRects(1, &r);
|
|
|
|
|
2021-11-29 17:22:25 +00:00
|
|
|
static const float white[] = { 1.f, 1.f, 1.f, 1.f };
|
|
|
|
if (color == nullptr)
|
|
|
|
color = white;
|
|
|
|
D3D11_MAPPED_SUBRESOURCE mappedSubres;
|
|
|
|
deviceContext->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubres);
|
|
|
|
memcpy(mappedSubres.pData, color, sizeof(float) * 4);
|
|
|
|
deviceContext->Unmap(constantBuffer, 0);
|
|
|
|
deviceContext->PSSetConstantBuffers(0, 1, &constantBuffer.get());
|
|
|
|
|
2021-11-26 17:08:41 +00:00
|
|
|
// Bind texture and draw
|
|
|
|
deviceContext->PSSetShaderResources(0, 1, &texView.get());
|
|
|
|
deviceContext->PSSetSamplers(0, 1, &sampler.get());
|
|
|
|
deviceContext->Draw(4, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
struct Vertex {
|
|
|
|
float x, y, u, v;
|
|
|
|
};
|
|
|
|
|
|
|
|
DX11Shaders *shaders = nullptr;
|
|
|
|
ComPtr<ID3D11Device> device;
|
|
|
|
ComPtr<ID3D11DeviceContext> deviceContext;
|
|
|
|
ComPtr<ID3D11InputLayout> inputLayout;
|
|
|
|
ComPtr<ID3D11Buffer> vertexBuffer;
|
2021-11-29 17:22:25 +00:00
|
|
|
ComPtr<ID3D11Buffer> constantBuffer;
|
2021-11-26 17:08:41 +00:00
|
|
|
ComPtr<ID3D11RasterizerState> rasterizerState;
|
|
|
|
ComPtr<ID3D11DepthStencilState> depthStencilState;
|
|
|
|
ComPtr<ID3D11VertexShader> vertexShader;
|
|
|
|
ComPtr<ID3D11VertexShader> rotateVertexShader;
|
|
|
|
ComPtr<ID3D11PixelShader> pixelShader;
|
|
|
|
};
|