157 lines
4.8 KiB
C++
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;
|
|
}
|