Files
aorii/src/renderer/backend/dx/dx_window.cpp
2024-10-20 17:29:11 +08:00

157 lines
4.8 KiB
C++

#include "dx_window.h"
#include <spdlog/spdlog.h>
#include "dx_renderer.h"
#include "misc/scope_exit.h"
using namespace aorii;
bool dx_window::create_surface(GLFWwindow* in_window) {
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
IDXGIDevice* dxgi_device = nullptr;
auto hr = d3d_device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgi_device));
if (FAILED(hr)) {
spdlog::critical("无法获取IDXGIDevice, 错误: {0}", hr);
return false;
}
ON_SCOPE_EXIT{
if (dxgi_device) dxgi_device->Release();
};
IDXGIAdapter* dxgi_adapter = nullptr;
hr = dxgi_device->GetAdapter(&dxgi_adapter);
if (FAILED(hr)) {
spdlog::critical("无法获取IDXGIAdapter, 错误: {0}", hr);
return false;
}
ON_SCOPE_EXIT{
if (dxgi_adapter) dxgi_adapter->Release();
};
IDXGIFactory2* dxgi_factory = nullptr;
hr = dxgi_adapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgi_factory));
if (FAILED(hr)) {
spdlog::critical("无法获取IDXGIFactory, 错误: {0}", hr);
return false;
}
ON_SCOPE_EXIT{
if (dxgi_factory) dxgi_factory->Release();
};
DXGI_SWAP_CHAIN_DESC1 sd = {};
sd.Width = 0; // 使用窗口宽度
sd.Height = 0; // 使用窗口高度
sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 2;
sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
sd.Flags = 0;
const auto hwnd = static_cast<HWND>(get_window_handle());
hr = dxgi_factory->CreateSwapChainForHwnd(d3d_device, hwnd, &sd, nullptr, nullptr, &swap_chain);
if (FAILED(hr)) {
spdlog::critical("无法创建交换链, 错误: {0}", hr);
return false;
}
hr = build_render_target_view();
if (FAILED(hr)) {
spdlog::critical("无法创建渲染模板视图, 错误: {0}", hr);
return false;
}
pipeline.set_pixel_shader("default_shader_pixel");
pipeline.set_vertex_shader("default_shader_vertex");
return true;
}
void dx_window::begin_frame() {
glfwMakeContextCurrent(get_glfw_window());
const auto render = aorii::get_renderer<dx_renderer>();
const auto d3d_context = render->get_d3d_context();
d3d_context->OMSetRenderTargets(1, &render_target_view, nullptr);
d3d_context->ClearRenderTargetView(render_target_view, clear_color);
pipeline.use();
float random_r = static_cast<float>(rand()) / RAND_MAX;
float random_g = static_cast<float>(rand()) / RAND_MAX;
float random_b = static_cast<float>(rand()) / RAND_MAX;
linear_color random_color = {random_r, random_g, random_b, 1.0f};
const vertex_type v1 {{-0.5f, 0.5f, 0.0f}, random_color };
const vertex_type v2 {{0.5f, 0.5f, 0.0f}, random_color };
const vertex_type v3 {{-0.5f, -0.5f, 0.0f}, random_color };
const vertex_type v4 {{0.5f, -0.5f, 0.0f}, random_color };
const vertex_type vertices[] = {
v1, v2, v3, v4
};
auto vertex_buffer = pipeline.lock_vertex_buffer();
std::ranges::copy(vertices, vertex_buffer.begin());
pipeline.unlock_vertex_buffer();
pipeline.draw();
swap_chain->Present(1, 0);
}
void dx_window::end_frame() {
}
void dx_window::on_resize(const Eigen::Vector2i& in_size) {
if (in_size.isZero())
return;
if (render_target_view) {
render_target_view->Release();
render_target_view = nullptr;
}
auto hr = swap_chain->ResizeBuffers(0, in_size.x(), in_size.y(), DXGI_FORMAT_UNKNOWN, 0);
if (FAILED(hr)) {
spdlog::critical("Failed to resize window. Error: {0}", hr);
return;
}
build_render_target_view();
}
HRESULT dx_window::build_render_target_view() {
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
const auto d3d_context = aorii::get_renderer<dx_renderer>()->get_d3d_context();
ID3D11Texture2D* back_buffer = nullptr;
auto hr = swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&back_buffer);
if (FAILED(hr)) {
spdlog::critical("Failed to get back buffer. Error: {0}", hr);
return hr;
}
ON_SCOPE_EXIT{
if (back_buffer) back_buffer->Release();
};
hr = d3d_device->CreateRenderTargetView(back_buffer, nullptr, &render_target_view);
if (FAILED(hr)) {
spdlog::critical("Failed to create render target. Error: {0}", hr);
return hr;
}
auto framebuffer_size = get_framebuffer_size();
D3D11_VIEWPORT viewport = {};
viewport.Width = (float)framebuffer_size.x();
viewport.Height = (float)framebuffer_size.y();
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
d3d_context->RSSetViewports(1, &viewport);
return hr;
}