gs_draw
2024-07-08
5
0
gs_draw(GS_TRISTRIP, 0, 0);
最终调用的是device_draw函数:
void device_draw(gs_device_t *device, enum gs_draw_mode draw_mode,
uint32_t start_vert, uint32_t num_verts)
{
try {
if (!device->curVertexShader)
throw "No vertex shader specified";
if (!device->curPixelShader)
throw "No pixel shader specified";
if (!device->curVertexBuffer && (num_verts == 0))
throw "No vertex buffer specified";
if (!device->curSwapChain && !device->curRenderTarget)
throw "No render target or swap chain to render to";
//设直渲染目标像
device->FlushOutputViews();
gs_effect_t *effect = gs_get_effect();
if (effect)
gs_effect_update_params(effect);
device->LoadVertexBufferData(); //IASetVertexBuffers
device->UpdateBlendState(); //OMSetBlendState
device->UpdateRasterState(); //光栅化配置
device->UpdateZStencilState(); //OMSetDepthStencilState
device->UpdateViewProjMatrix();
device->curVertexShader->UploadParams();//顶点着以器参数
device->curPixelShader->UploadParams(); //像系着色器参数
} catch (const char *error) {
blog(LOG_ERROR, "device_draw (D3D11): %s", error);
return;
} catch (const HRError &error) {
blog(LOG_ERROR, "device_draw (D3D11): %s (%08lX)", error.str,
error.hr);
LogD3D11ErrorDetails(error, device);
return;
}
//转换为d3d11的绘制模式
D3D11_PRIMITIVE_TOPOLOGY newTopology = ConvertGSTopology(draw_mode);
if (device->curToplogy != newTopology) {
device->context->IASetPrimitiveTopology(newTopology);
device->curToplogy = newTopology;
}
if (device->curIndexBuffer) {
if (num_verts == 0)
num_verts = (uint32_t)device->curIndexBuffer->num;
device->context->DrawIndexed(num_verts, start_vert, 0);
} else {
if (num_verts == 0)
num_verts = (uint32_t)device->curVertexBuffer->numVerts;
device->context->Draw(num_verts, start_vert);
}
}
gs_get_effect就是获取当前的effect
gs_effect_t *gs_get_effect(void)
{
if (!gs_valid("gs_get_effect"))
return NULL;
return thread_graphics ? thread_graphics->cur_effect : NULL;
}
并使用gs_effect_update_params将effect上的参数更新上到着色器中。
这里比较重要的就是FlushOutputViews。
void gs_device::FlushOutputViews()
{
if (curFramebufferInvalidate)
{
ID3D11RenderTargetView *rtv = nullptr;
if (curRenderTarget)
{
const int i = curRenderSide;
rtv = curFramebufferSrgb ? curRenderTarget->renderTargetLinear[i].Get() : curRenderTarget->renderTarget[i].Get();
if (!rtv)
{
blog(LOG_ERROR, "device_draw (D3D11): texture is not a render target");
return;
}
}
ID3D11DepthStencilView *dsv = nullptr;
if (curZStencilBuffer)
dsv = curZStencilBuffer->view;
context->OMSetRenderTargets(1, &rtv, dsv);
curFramebufferInvalidate = false;
}
}
而curRenderTarget是通过device_set_render_target_internal设置的。
static void device_set_render_target_internal(gs_device_t *device,
gs_texture_t *tex,
gs_zstencil_t *zstencil,
enum gs_color_space space)
{
//只有在渲染display时,会调用display的gs_load_swapchain
if (device->curSwapChain)
{
if (!tex)
tex = &device->curSwapChain->target;
if (!zstencil)
zstencil = &device->curSwapChain->zs;
}
if (device->curRenderTarget == tex && device->curZStencilBuffer == zstencil)
{
device->curColorSpace = space;
}
if (tex && tex->type != GS_TEXTURE_2D)
{
blog(LOG_ERROR, "device_set_render_target_internal (D3D11): texture is not a 2D texture");
return;
}
gs_texture_2d *const tex2d = static_cast<gs_texture_2d *>(tex);
if (device->curRenderTarget != tex2d || device->curRenderSide != 0 || device->curZStencilBuffer != zstencil)
{
device->curRenderTarget = tex2d;
device->curZStencilBuffer = zstencil;
device->curRenderSide = 0;
device->curColorSpace = space;
device->curFramebufferInvalidate = true;
}
}
二次被封装为:
void device_set_render_target(gs_device_t *device, gs_texture_t *tex,
gs_zstencil_t *zstencil)
{
device_set_render_target_internal(device, tex, zstencil, GS_CS_SRGB);
}
void device_set_render_target_with_color_space(gs_device_t *device,
gs_texture_t *tex,
gs_zstencil_t *zstencil,
enum gs_color_space space)
{
device_set_render_target_internal(device, tex, zstencil, space);
}
void device_load_swapchain(gs_device_t *device, gs_swapchain_t *swapchain)
{
gs_texture_t *target = device->curRenderTarget;
gs_zstencil_t *zs = device->curZStencilBuffer;
bool is_cube =
device->curRenderTarget
? (device->curRenderTarget->type == GS_TEXTURE_CUBE)
: false;
if (device->curSwapChain) {
if (target == &device->curSwapChain->target)
target = NULL;
if (zs == &device->curSwapChain->zs)
zs = NULL;
}
device->curSwapChain = swapchain;
if (is_cube) {
device_set_cube_render_target(device, target,
device->curRenderSide, zs);
} else {
const enum gs_color_space space = swapchain ? swapchain->space
: GS_CS_SRGB;
device_set_render_target_internal(device, target, zs, space);
}
}
如render_main_texture就是通过调用device_set_render_target_with_color_space设置的渲染纹理: https://www.pnpon.com/article/detail-709.html