核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
99 lines
4.6 KiB
C
99 lines
4.6 KiB
C
#include "graphics_device.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
GraphicsDevice* graphics_device_create(void) {
|
|
return (GraphicsDevice*)calloc(1, sizeof(GraphicsDevice));
|
|
}
|
|
|
|
void graphics_device_destroy(GraphicsDevice* d) {
|
|
if (!d) return;
|
|
if (d->depth_stencil) d->depth_stencil->lpVtbl->Release(d->depth_stencil);
|
|
if (d->depth_texture) d->depth_texture->lpVtbl->Release(d->depth_texture);
|
|
if (d->render_target) d->render_target->lpVtbl->Release(d->render_target);
|
|
if (d->swap_chain) d->swap_chain->lpVtbl->Release(d->swap_chain);
|
|
if (d->context) d->context->lpVtbl->Release(d->context);
|
|
if (d->device) d->device->lpVtbl->Release(d->device);
|
|
free(d);
|
|
}
|
|
|
|
static int create_depth_stencil(GraphicsDevice* d, uint32_t w, uint32_t h) {
|
|
D3D11_TEXTURE2D_DESC desc = {0};
|
|
desc.Width = w; desc.Height = h;
|
|
desc.MipLevels = 1; desc.ArraySize = 1;
|
|
desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
|
desc.SampleDesc.Count = 1;
|
|
desc.Usage = D3D11_USAGE_DEFAULT;
|
|
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
|
HRESULT hr = d->device->lpVtbl->CreateTexture2D(d->device, &desc, NULL, &d->depth_texture);
|
|
if (FAILED(hr)) return 0;
|
|
D3D11_DEPTH_STENCIL_VIEW_DESC dsv = {0};
|
|
dsv.Format = desc.Format;
|
|
dsv.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
|
hr = d->device->lpVtbl->CreateDepthStencilView(d->device, (ID3D11Resource*)d->depth_texture, &dsv, &d->depth_stencil);
|
|
return SUCCEEDED(hr);
|
|
}
|
|
|
|
int graphics_device_init(GraphicsDevice* d, void* hwnd, uint32_t w, uint32_t h, int vsync) {
|
|
d->width = w; d->height = h; d->vsync = vsync;
|
|
DXGI_SWAP_CHAIN_DESC scd = {0};
|
|
scd.BufferCount = 1;
|
|
scd.BufferDesc.Width = w;
|
|
scd.BufferDesc.Height = h;
|
|
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
scd.BufferDesc.RefreshRate.Numerator = 60;
|
|
scd.BufferDesc.RefreshRate.Denominator = 1;
|
|
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
scd.OutputWindow = (HWND)hwnd;
|
|
scd.SampleDesc.Count = 1;
|
|
scd.Windowed = TRUE;
|
|
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
|
D3D_FEATURE_LEVEL levels[] = {D3D_FEATURE_LEVEL_11_0};
|
|
UINT flags = 0;
|
|
#ifdef _DEBUG
|
|
flags |= D3D11_CREATE_DEVICE_DEBUG;
|
|
#endif
|
|
HRESULT hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, levels, 1, D3D11_SDK_VERSION, &scd, &d->swap_chain, &d->device, NULL, &d->context);
|
|
if (FAILED(hr)) return 0;
|
|
ID3D11Texture2D* back_buffer = NULL;
|
|
d->swap_chain->lpVtbl->GetBuffer(d->swap_chain, 0, &IID_ID3D11Texture2D, (void**)&back_buffer);
|
|
d->device->lpVtbl->CreateRenderTargetView(d->device, (ID3D11Resource*)back_buffer, NULL, &d->render_target);
|
|
if (back_buffer) back_buffer->lpVtbl->Release(back_buffer);
|
|
create_depth_stencil(d, w, h);
|
|
d->context->lpVtbl->OMSetRenderTargets(d->context, 1, &d->render_target, d->depth_stencil);
|
|
D3D11_VIEWPORT vp = {0};
|
|
vp.Width = (float)w; vp.Height = (float)h;
|
|
vp.MaxDepth = 1.0f;
|
|
d->context->lpVtbl->RSSetViewports(d->context, 1, &vp);
|
|
return 1;
|
|
}
|
|
|
|
void graphics_device_resize(GraphicsDevice* d, uint32_t w, uint32_t h) {
|
|
if (w == 0 || h == 0) return;
|
|
d->context->lpVtbl->OMSetRenderTargets(d->context, 0, NULL, NULL);
|
|
if (d->render_target) { d->render_target->lpVtbl->Release(d->render_target); d->render_target = NULL; }
|
|
if (d->depth_stencil) { d->depth_stencil->lpVtbl->Release(d->depth_stencil); d->depth_stencil = NULL; }
|
|
if (d->depth_texture) { d->depth_texture->lpVtbl->Release(d->depth_texture); d->depth_texture = NULL; }
|
|
d->swap_chain->lpVtbl->ResizeBuffers(d->swap_chain, 0, w, h, DXGI_FORMAT_UNKNOWN, 0);
|
|
ID3D11Texture2D* back_buffer = NULL;
|
|
d->swap_chain->lpVtbl->GetBuffer(d->swap_chain, 0, &IID_ID3D11Texture2D, (void**)&back_buffer);
|
|
d->device->lpVtbl->CreateRenderTargetView(d->device, (ID3D11Resource*)back_buffer, NULL, &d->render_target);
|
|
if (back_buffer) back_buffer->lpVtbl->Release(back_buffer);
|
|
create_depth_stencil(d, w, h);
|
|
d->context->lpVtbl->OMSetRenderTargets(d->context, 1, &d->render_target, d->depth_stencil);
|
|
D3D11_VIEWPORT vp = {0};
|
|
vp.Width = (float)w; vp.Height = (float)h; vp.MaxDepth = 1.0f;
|
|
d->context->lpVtbl->RSSetViewports(d->context, 1, &vp);
|
|
d->width = w; d->height = h;
|
|
}
|
|
|
|
void graphics_device_clear(GraphicsDevice* d, float r, float g, float b, float a) {
|
|
float color[4] = {r, g, b, a};
|
|
d->context->lpVtbl->ClearRenderTargetView(d->context, d->render_target, color);
|
|
d->context->lpVtbl->ClearDepthStencilView(d->context, d->depth_stencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
|
|
}
|
|
|
|
void graphics_device_present(GraphicsDevice* d) {
|
|
d->swap_chain->lpVtbl->Present(d->swap_chain, d->vsync ? 1 : 0, 0);
|
|
}
|