Files
lity3d/Engine/Rendering/graphics_device.c
T
shuiyu1123 8b76ae6a0d fix: set default DepthStencilState in graphics_device_init
Prevents UILayer init from breaking 3D rendering pipeline.
Creates explicit LESS_EQUAL depth state at init time.
2026-07-11 12:50:48 +08:00

111 lines
5.1 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);
// 设置默认深度状态 (避免 UILayer init 破坏)
D3D11_DEPTH_STENCIL_DESC dsd = {0};
dsd.DepthEnable = TRUE;
dsd.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dsd.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
ID3D11DepthStencilState* default_dss = NULL;
d->device->lpVtbl->CreateDepthStencilState(d->device, &dsd, &default_dss);
if (default_dss) {
d->context->lpVtbl->OMSetDepthStencilState(d->context, default_dss, 0);
default_dss->lpVtbl->Release(default_dss);
}
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);
}