允许添加自定义命令到着色器编译函数
优化dx_pipeline代码结构
This commit is contained in:
parent
5220ba6e39
commit
64d7894981
@ -1,4 +1,3 @@
|
||||
|
||||
function(compile_slang_shaders input_file stage entry_point)
|
||||
# 保证输出目录存在
|
||||
if (NOT DEFINED SHADER_OUTPUT_DIR)
|
||||
@ -28,7 +27,7 @@ function(compile_slang_shaders input_file stage entry_point)
|
||||
set(output_file ${output_dir}/${filename}_${entry_point}.glsl)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
COMMAND slangc -target glsl -entry ${entry_point} -stage ${stage} -o ${output_file} ${input_file}
|
||||
COMMAND slangc -target glsl -entry ${entry_point} -stage ${stage} ${ARGN} -o ${output_file} ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to GLSL (${stage}, ${entry_point})"
|
||||
)
|
||||
@ -39,7 +38,7 @@ function(compile_slang_shaders input_file stage entry_point)
|
||||
set(output_file ${output_dir}/${filename}_${entry_point}.dxbc)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
COMMAND slangc -target dxbc -profile ${profile} -entry ${entry_point} -stage ${stage} -o ${output_file} ${input_file}
|
||||
COMMAND slangc -target dxbc -profile ${profile} -entry ${entry_point} -stage ${stage} ${ARGN} -o ${output_file} ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to DXBC (${stage}, ${entry_point}) with profile ${profile}"
|
||||
)
|
||||
@ -50,7 +49,7 @@ function(compile_slang_shaders input_file stage entry_point)
|
||||
set(output_file ${output_dir}/${filename}_${entry_point}.spirv)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
COMMAND slangc -target spirv -entry ${entry_point} -stage ${stage} -o ${output_file} ${input_file}
|
||||
COMMAND slangc -target spirv -entry ${entry_point} -stage ${stage} ${ARGN} -o ${output_file} ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to SPIR-V (${stage}, ${entry_point})"
|
||||
)
|
||||
@ -61,7 +60,7 @@ function(compile_slang_shaders input_file stage entry_point)
|
||||
set(output_file ${output_dir}/${filename}_${entry_point}.metal)
|
||||
add_custom_command(
|
||||
OUTPUT ${output_file}
|
||||
COMMAND slangc -target msl -entry ${entry_point} -stage ${stage} -o ${output_file} ${input_file}
|
||||
COMMAND slangc -target msl -entry ${entry_point} -stage ${stage} ${ARGN} -o ${output_file} ${input_file}
|
||||
DEPENDS ${input_file}
|
||||
COMMENT "Compiling ${input_file} to Metal Shading Language (${stage}, ${entry_point})"
|
||||
)
|
||||
|
@ -58,7 +58,7 @@ if (NOT DEFINED SHADER_OUTPUT_DIR)
|
||||
set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/shaders CACHE PATH "Output directory for compiled shaders")
|
||||
message(STATUS "SHADER_OUTPUT_DIR not defined, using default: ${SHADER_OUTPUT_DIR}")
|
||||
endif ()
|
||||
compile_slang_shaders(${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang vertex vertex_main)
|
||||
compile_slang_shaders(${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang pixel pixel_main)
|
||||
compile_slang_shaders(${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang pixel rounded_rect_pixel_main)
|
||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang" "vertex" "vertex_main")
|
||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang" "pixel" "pixel_main")
|
||||
compile_slang_shaders("${CMAKE_CURRENT_SOURCE_DIR}/shader/default_shader.slang" "pixel" "rounded_rect_pixel_main" -D IS_ROUNDED_RECT)
|
||||
add_compile_shaders_target("compile_aorii_shaders" ${PROJECT_NAME})
|
||||
|
@ -32,6 +32,7 @@ void dx_pipeline::draw() {
|
||||
d3d_context->IASetVertexBuffers(0, 1, &v_buffer, &stride, &offset);
|
||||
d3d_context->IASetIndexBuffer(i_buffer, DXGI_FORMAT_R32_UINT, 0);
|
||||
d3d_context->VSSetConstantBuffers(0, 1, &c_buffer);
|
||||
d3d_context->PSSetConstantBuffers(0, 1, &c_buffer);
|
||||
|
||||
// 设置图元拓扑
|
||||
d3d_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
@ -40,9 +41,10 @@ void dx_pipeline::draw() {
|
||||
d3d_context->Draw(vertex_buffer->get_size(), 0);
|
||||
}
|
||||
|
||||
void dx_pipeline::load_pixel_shader() {
|
||||
void dx_pipeline::load_pixel_shader(const char* shader_name) {
|
||||
if (pixel_shader) { pixel_shader->Release(); }
|
||||
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
|
||||
const auto& shader_code = load_shader(AORII_DEFAULT_PIXEL_SHADER_NAME);
|
||||
const auto& shader_code = load_shader(shader_name);
|
||||
const auto hr = d3d_device->CreatePixelShader(shader_code.data(), shader_code.size(), nullptr, &pixel_shader);
|
||||
if (FAILED(hr)) { spdlog::critical("无法创建像素着色器: {0}", hr); }
|
||||
}
|
||||
@ -64,16 +66,8 @@ void dx_pipeline::load_vertex_shader() {
|
||||
spdlog::critical("无法创建输入布局: {0}", hr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void dx_pipeline::build_vertex_buffer(int vertex_count) {
|
||||
delete vertex_buffer;
|
||||
vertex_buffer = new dx_buffer<aorii_vertex_type>(buffer_type::vertex, vertex_count);
|
||||
}
|
||||
|
||||
void dx_pipeline::build_index_buffer(int triangle_count) {
|
||||
delete triangle_buffer;
|
||||
triangle_buffer = new dx_buffer<aorii_triangle_type>(buffer_type::index, triangle_count);
|
||||
vertex_buffer = new dx_buffer<aorii_vertex_type>(buffer_type::vertex, 4);
|
||||
triangle_buffer = new dx_buffer<aorii_triangle_type>(buffer_type::index, 2);
|
||||
}
|
||||
|
||||
void dx_pipeline::build_constant_buffer() {
|
||||
|
@ -14,16 +14,15 @@ public:
|
||||
void use() override;
|
||||
void draw() override;
|
||||
|
||||
void load_pixel_shader();
|
||||
void load_pixel_shader(const char* shader_name);
|
||||
void load_vertex_shader();
|
||||
void build_vertex_buffer(int vertex_count);
|
||||
void build_index_buffer(int triangle_count);
|
||||
|
||||
void build_constant_buffer();
|
||||
|
||||
void set_triangle(const std::span<const aorii_vertex_type>& in_vertexes, const std::span<const aorii_triangle_type>& in_triangles) override;
|
||||
|
||||
aorii_constant_buffer_type* lock_constant_buffer();
|
||||
void unlock_constant_buffer();
|
||||
aorii_constant_buffer_type* lock_constant_buffer() override;
|
||||
void unlock_constant_buffer() override;
|
||||
private:
|
||||
static std::vector<char> load_shader(const std::string& shader_name);
|
||||
|
||||
|
@ -8,14 +8,8 @@
|
||||
#include <math.h>
|
||||
|
||||
using namespace aorii;
|
||||
dx_pipeline pipeline;
|
||||
|
||||
void dx_pipeline_begin_frame(const Eigen::Matrix4f& projection_matrix) {
|
||||
auto constant_buffer = pipeline.lock_constant_buffer();
|
||||
constant_buffer->projection_matrix = projection_matrix;
|
||||
pipeline.unlock_constant_buffer();
|
||||
pipeline.use();
|
||||
}
|
||||
dx_pipeline default_pipeline;
|
||||
dx_pipeline rounded_rect_pipeline;
|
||||
|
||||
bool dx_window::create_surface(GLFWwindow* in_window) {
|
||||
const auto d3d_device = aorii::get_renderer<dx_renderer>()->get_d3d_device();
|
||||
@ -68,9 +62,8 @@ bool dx_window::create_surface(GLFWwindow* in_window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pipeline.build_vertex_buffer(4);
|
||||
pipeline.build_index_buffer(2);
|
||||
pipeline.build_constant_buffer();
|
||||
default_pipeline.build_constant_buffer();
|
||||
rounded_rect_pipeline.build_constant_buffer();
|
||||
|
||||
hr = build_render_target_view();
|
||||
if (FAILED(hr)) {
|
||||
@ -78,9 +71,14 @@ bool dx_window::create_surface(GLFWwindow* in_window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pipeline.load_pixel_shader();
|
||||
pipeline.load_vertex_shader();
|
||||
context.set_default_pipeline(&pipeline);
|
||||
default_pipeline.load_pixel_shader(AORII_DEFAULT_PIXEL_SHADER_NAME);
|
||||
default_pipeline.load_vertex_shader();
|
||||
|
||||
rounded_rect_pipeline.load_pixel_shader(AORII_DEFAULT_ROUNDED_RECT_PIXEL_SHADER_NAME);
|
||||
rounded_rect_pipeline.load_vertex_shader();
|
||||
|
||||
context.set_default_pipeline(&default_pipeline);
|
||||
context.set_rounded_rectangular_pipeline(&rounded_rect_pipeline);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -94,9 +92,7 @@ void dx_window::begin_frame() {
|
||||
d3d_context->OMSetRenderTargets(1, &render_target_view, nullptr);
|
||||
d3d_context->ClearRenderTargetView(render_target_view, clear_color);
|
||||
|
||||
dx_pipeline_begin_frame(projection_matrix);
|
||||
|
||||
{
|
||||
if constexpr (false) {
|
||||
static std::chrono::duration<double> timer = {};
|
||||
static linear_color random_color = { 0, 0, 0, 1 };
|
||||
static bool is_white = false;
|
||||
@ -117,7 +113,6 @@ void dx_window::begin_frame() {
|
||||
is_white = false;
|
||||
random_color = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if (random_color.r < 1) {
|
||||
@ -141,6 +136,7 @@ void dx_window::begin_frame() {
|
||||
}
|
||||
}
|
||||
|
||||
context.draw_rounded_rectangle({ 100, 100 }, { 100, 100 }, { 1, 0, 0, 1 }, 10);
|
||||
context.flush();
|
||||
|
||||
swap_chain->Present(1, 0);
|
||||
@ -197,7 +193,16 @@ HRESULT dx_window::build_render_target_view() {
|
||||
viewport.TopLeftY = 0.0f;
|
||||
d3d_context->RSSetViewports(1, &viewport);
|
||||
|
||||
projection_matrix = get_projection_matrix().transpose();
|
||||
const auto& projection_matrix = get_projection_matrix().transpose();
|
||||
|
||||
// 更新常量缓冲区
|
||||
const auto constant_buffer = default_pipeline.lock_constant_buffer();
|
||||
constant_buffer->projection_matrix = projection_matrix;
|
||||
default_pipeline.unlock_constant_buffer();
|
||||
|
||||
const auto rounded_rect_constant_buffer = rounded_rect_pipeline.lock_constant_buffer();
|
||||
rounded_rect_constant_buffer->projection_matrix = projection_matrix;
|
||||
rounded_rect_pipeline.unlock_constant_buffer();
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -19,5 +19,4 @@ private:
|
||||
renderer_context context;
|
||||
IDXGISwapChain1* swap_chain = nullptr;
|
||||
ID3D11RenderTargetView* render_target_view = nullptr;
|
||||
Eigen::Matrix4f projection_matrix;
|
||||
};
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "misc/color.h"
|
||||
|
||||
#define AORII_DEFAULT_PIXEL_SHADER_NAME "default_shader_pixel_main"
|
||||
#define AORII_DEFAULT_ROUNDED_RECT_PIXEL_SHADER_NAME "default_shader_rounded_rect_pixel_main"
|
||||
#define AORII_DEFAULT_VERTEX_SHADER_NAME "default_shader_vertex_main"
|
||||
|
||||
struct aorii_vertex {
|
||||
@ -17,6 +18,8 @@ struct aorii_triangle {
|
||||
};
|
||||
struct aorii_constant_buffer {
|
||||
Eigen::Matrix4f projection_matrix;
|
||||
Eigen::Vector2f size;
|
||||
float radius;
|
||||
};
|
||||
using aorii_vertex_type = aorii_vertex;
|
||||
using aorii_triangle_type = aorii_triangle;
|
||||
@ -31,6 +34,9 @@ public:
|
||||
virtual void draw() = 0;
|
||||
|
||||
virtual void set_triangle(const std::span<const aorii_vertex_type>& in_vertexes, const std::span<const aorii_triangle_type>& in_triangles) = 0;
|
||||
|
||||
virtual aorii_constant_buffer_type* lock_constant_buffer() = 0;
|
||||
virtual void unlock_constant_buffer() = 0;
|
||||
};
|
||||
|
||||
class custom_pipeline : public pipeline {
|
||||
|
@ -23,8 +23,32 @@ void renderer_context::draw_rectangle(const Eigen::Vector2i& in_pos, const Eigen
|
||||
}
|
||||
|
||||
void renderer_context::draw_rounded_rectangle(const Eigen::Vector2i& in_pos, const Eigen::Vector2i& in_size, const linear_color& in_color, float in_radius) {
|
||||
auto constant_buffer = rounded_rectangular_pipeline->lock_constant_buffer();
|
||||
constant_buffer->size = in_size.cast<float>();
|
||||
constant_buffer->radius = in_radius;
|
||||
rounded_rectangular_pipeline->unlock_constant_buffer();
|
||||
|
||||
switch_pipeline(rounded_rectangular_pipeline);
|
||||
|
||||
const aorii_vertex_type v1{ { in_pos.x(), in_pos.y() }, in_color }; // 左上角
|
||||
const aorii_vertex_type v2{ { in_pos.x() + in_size.x(), in_pos.y() }, in_color }; // 右上角
|
||||
const aorii_vertex_type v3{ { in_pos.x(), in_pos.y() + in_size.y() }, in_color }; // 左下角
|
||||
const aorii_vertex_type v4{ { in_pos.x() + in_size.x(), in_pos.y() + in_size.y() }, in_color }; // 右下角
|
||||
|
||||
const uint32_t index1 = vertices.size();
|
||||
vertices.push_back(v1);
|
||||
const uint32_t index2 = vertices.size();
|
||||
vertices.push_back(v2);
|
||||
const uint32_t index3 = vertices.size();
|
||||
vertices.push_back(v3);
|
||||
const uint32_t index4 = vertices.size();
|
||||
vertices.push_back(v4);
|
||||
|
||||
const aorii_triangle_type t1 = { index1, index2, index3 };
|
||||
const aorii_triangle_type t2 = { index2, index3, index4 };
|
||||
triangles.push_back(t1);
|
||||
triangles.push_back(t2);
|
||||
|
||||
// 立刻绘制并重置管线, 因为下一个绘制命令的参数可能不同, 所以无法合批
|
||||
flush();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <Eigen/Eigen>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include "core/pipeline/pipeline.h"
|
||||
|
||||
@ -34,6 +34,9 @@ public:
|
||||
void set_default_pipeline(pipeline* in_pipeline) {
|
||||
default_pipeline = in_pipeline;
|
||||
}
|
||||
void set_rounded_rectangular_pipeline(pipeline* in_pipeline) {
|
||||
rounded_rectangular_pipeline = in_pipeline;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
vertices.clear();
|
||||
@ -56,9 +59,14 @@ public:
|
||||
}
|
||||
protected:
|
||||
void switch_pipeline(pipeline* in_pipeline) {
|
||||
#if DEBUG
|
||||
if (!in_pipeline)
|
||||
spdlog::critical("尝试切换到空管线");
|
||||
#endif
|
||||
if (current_pipeline != in_pipeline) {
|
||||
flush();
|
||||
current_pipeline = in_pipeline;
|
||||
current_pipeline->use();
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
@ -1,14 +1,10 @@
|
||||
struct MatrixBuffer
|
||||
struct ParamBuffer
|
||||
{
|
||||
matrix transform;
|
||||
};
|
||||
struct RoundedRectBuffer
|
||||
{
|
||||
float2 size; // 像素单位
|
||||
float radius; // 像素单位
|
||||
};
|
||||
ParameterBlock<MatrixBuffer> matrix_buffer : register(b0);
|
||||
ParameterBlock<RoundedRectBuffer> rounded_rect_buffer : register(b1);
|
||||
ParameterBlock<ParamBuffer> param_buffer : register(b0);
|
||||
SamplerState texture_sampler : register(s0);
|
||||
|
||||
struct VSInput {
|
||||
@ -22,20 +18,6 @@ struct PSInput {
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
PSInput vertex_main(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
output.position = mul(float4(input.position, 0.0, 1.0), matrix_buffer.transform);
|
||||
output.color = input.color;
|
||||
output.uv = input.position + 0.5;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 pixel_main(PSInput input) : SV_TARGET
|
||||
{
|
||||
return input.color;
|
||||
}
|
||||
|
||||
// 计算点到矩形边的最小距离
|
||||
float rounded_box_SDF(float2 center_position, float2 size, float radius)
|
||||
{
|
||||
@ -43,11 +25,21 @@ float rounded_box_SDF(float2 center_position, float2 size, float radius)
|
||||
return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
|
||||
}
|
||||
|
||||
PSInput vertex_main(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
output.position = mul(float4(input.position, 0.0, 1.0), param_buffer.transform);
|
||||
output.color = input.color;
|
||||
output.uv = (input.position + float2(1.0, 1.0)) * 0.5; // 将 [-1, 1] 映射到 [0, 1]
|
||||
return output;
|
||||
}
|
||||
|
||||
#ifdef IS_ROUNDED_RECT
|
||||
// 圆角矩形像素着色器
|
||||
float4 rounded_rect_pixel_main(PSInput input) : SV_TARGET
|
||||
{
|
||||
float2 size = rounded_rect_buffer.size;
|
||||
float radius = rounded_rect_buffer.radius;
|
||||
float2 size = param_buffer.size;
|
||||
float radius = param_buffer.radius;
|
||||
|
||||
// 将UV坐标转换为中心坐标系统
|
||||
float2 center_position = (input.uv - 0.5) * size;
|
||||
@ -59,5 +51,11 @@ float4 rounded_rect_pixel_main(PSInput input) : SV_TARGET
|
||||
float alpha = 1.0 - smoothstep(-1.0, 1.0, distance);
|
||||
|
||||
// 返回最终颜色
|
||||
return float4(input.color.xyz, input.color.a * alpha);
|
||||
return float4(float3(1, 1, 1), input.color.a * alpha);
|
||||
}
|
||||
#else
|
||||
float4 pixel_main(PSInput input) : SV_TARGET
|
||||
{
|
||||
return input.color;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user