Triangle with per vertex colors
This commit is contained in:
commit
270132a58e
57
.gitignore
vendored
Normal file
57
.gitignore
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
SDL3/
|
||||
build/
|
||||
.cache/
|
||||
.vscode/
|
||||
75
CMakeLists.txt
Normal file
75
CMakeLists.txt
Normal file
@ -0,0 +1,75 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(sdlgpu1 VERSION 0.1.0 LANGUAGES C CXX)
|
||||
|
||||
SET(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE)
|
||||
set(EXE_NAME ${CMAKE_PROJECT_NAME})
|
||||
|
||||
#set(PROGRAM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vulkanapp.cc)
|
||||
|
||||
# Get our GLSL shaders
|
||||
set(SHADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/shaders)
|
||||
set(SHADER_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
file(GLOB SHADERS ${SHADER_DIR}/*.vert
|
||||
${SHADER_DIR}/*.frag
|
||||
${SHADER_DIR}/*.comp
|
||||
${SHADER_DIR}/*.geom
|
||||
${SHADER_DIR}/*.tesc
|
||||
${SHADER_DIR}/*.tese
|
||||
${SHADER_DIR}/*.mesh
|
||||
${SHADER_DIR}/*.task
|
||||
${SHADER_DIR}/*.rgen
|
||||
${SHADER_DIR}/*.rchit
|
||||
${SHADER_DIR}/*.rmiss
|
||||
)
|
||||
|
||||
option(SDL3_NONSYSTEM "Use SDL2 from folder in source tree" ON)
|
||||
|
||||
if(SDL3_NONSYSTEM)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/SDL3 ${CMAKE_CURRENT_BINARY_DIR}/SDL3 EXCLUDE_FROM_ALL)
|
||||
else()
|
||||
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3-shared)
|
||||
endif()
|
||||
|
||||
find_package(Vulkan REQUIRED COMPONENTS glslc)
|
||||
|
||||
# Compile each shader
|
||||
foreach(SHADER IN LISTS SHADERS)
|
||||
get_filename_component(FILENAME ${SHADER} NAME)
|
||||
add_custom_command(OUTPUT ${SHADER_BIN_DIR}/${FILENAME}.spv
|
||||
COMMAND ${Vulkan_GLSLC_EXECUTABLE} ${SHADER} -o ${SHADER_BIN_DIR}/${FILENAME}.spv
|
||||
DEPENDS ${SHADER}
|
||||
COMMENT "Compiling Shader ${FILENAME}")
|
||||
list(APPEND SPV_SHADERS ${SHADER_BIN_DIR}/${FILENAME}.spv)
|
||||
endForeach()
|
||||
|
||||
# Shader target
|
||||
add_custom_target(shaders ALL DEPENDS ${SPV_SHADERS})
|
||||
|
||||
add_executable(${EXE_NAME} ${CMAKE_SOURCE_DIR}/main.c ${SHADERS})
|
||||
|
||||
if(WIN32)
|
||||
add_custom_command(
|
||||
TARGET ${EXE_NAME} POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy $<TARGET_FILE:SDL3::SDL3-shared> $<TARGET_FILE_DIR:${EXE_NAME}>
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(${EXE_NAME}
|
||||
PROPERTIES
|
||||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
CXX_EXTENSIONS ON
|
||||
)
|
||||
|
||||
target_include_directories(${EXE_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
||||
add_dependencies(${EXE_NAME} shaders)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
target_compile_options(${EXE_NAME} PRIVATE -Wall -Wextra)
|
||||
elseif(MSVC)
|
||||
target_compile_options(${EXE_NAME} PRIVATE /W4)
|
||||
endif()
|
||||
|
||||
# Linking
|
||||
target_link_libraries(${EXE_NAME} PRIVATE SDL3::SDL3)
|
||||
201
main.c
Normal file
201
main.c
Normal file
@ -0,0 +1,201 @@
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
SDL_GPUShader *loadShader(SDL_GPUDevice *device,
|
||||
const char *filename,
|
||||
Uint32 samplerCount,
|
||||
Uint32 uniformBufferCount,
|
||||
Uint32 storageBufferCount,
|
||||
Uint32 storageTextureCount) {
|
||||
SDL_GPUShaderStage stage;
|
||||
if(SDL_strstr(filename, ".vert"))
|
||||
stage = SDL_GPU_SHADERSTAGE_VERTEX;
|
||||
else if(SDL_strstr(filename, ".frag"))
|
||||
stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
|
||||
else {
|
||||
SDL_Log("Invalid shader stage!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_GPUShaderFormat backendFmt = SDL_GetGPUShaderFormats(device);
|
||||
|
||||
SDL_GPUShaderFormat format = SDL_GPU_SHADERFORMAT_INVALID;
|
||||
const char *entryPoint;
|
||||
|
||||
if(backendFmt & SDL_GPU_SHADERFORMAT_SPIRV) {
|
||||
format = SDL_GPU_SHADERFORMAT_SPIRV;
|
||||
entryPoint = "main";
|
||||
} else {
|
||||
SDL_Log("Unsupported shader format!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t fSize = 0;
|
||||
void *byteCode = SDL_LoadFile(filename, &fSize);
|
||||
|
||||
if(byteCode == NULL) {
|
||||
SDL_Log("Could not load shader bytecode from file: %s", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_GPUShaderCreateInfo shaderInfo = {
|
||||
.code = (Uint8*)byteCode,
|
||||
.code_size = fSize,
|
||||
.entrypoint = entryPoint,
|
||||
.format = format,
|
||||
.stage = stage,
|
||||
.num_samplers = samplerCount,
|
||||
.num_uniform_buffers = uniformBufferCount,
|
||||
.num_storage_buffers = storageBufferCount,
|
||||
.num_storage_textures = storageTextureCount
|
||||
};
|
||||
SDL_GPUShader *shader = SDL_CreateGPUShader(device, &shaderInfo);
|
||||
if(shader == NULL) {
|
||||
SDL_Log("Could not create shader!");
|
||||
SDL_free(byteCode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_free(byteCode);
|
||||
return shader;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
SDL_Window *window = NULL;
|
||||
SDL_GPUDevice *GPUDevice = NULL;
|
||||
SDL_GPUTexture *swapchainTexture = NULL;
|
||||
SDL_GPUCommandBuffer *commandBuf = NULL;
|
||||
SDL_GPURenderPass *renderPass = NULL;
|
||||
|
||||
SDL_GPUShader *vertexShader = NULL;
|
||||
SDL_GPUShader *fragShader = NULL;
|
||||
|
||||
SDL_GPUGraphicsPipeline *pipeline = NULL;
|
||||
|
||||
bool done = false;
|
||||
|
||||
if(!SDL_Init(SDL_INIT_VIDEO)) {
|
||||
SDL_Log("Unable to initialize SDL3: %s", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create the GPU device
|
||||
GPUDevice = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV, true, "vulkan");
|
||||
|
||||
const char* device_driver = SDL_GetGPUDeviceDriver(GPUDevice);
|
||||
SDL_Log("Created GPU device with driver: %s\n", device_driver);
|
||||
|
||||
if(GPUDevice == NULL) {
|
||||
SDL_Log("Create GPU failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create the window
|
||||
window = SDL_CreateWindow("SDL3 Window", 640, 480, SDL_WINDOW_RESIZABLE);
|
||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
|
||||
|
||||
if (window == NULL) {
|
||||
SDL_Log("Could not create window: %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Tie the window to our GPU
|
||||
if(!SDL_ClaimWindowForGPUDevice(GPUDevice, window)) {
|
||||
SDL_Log("Claiming SDL3 window failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Shader time
|
||||
vertexShader = loadShader(GPUDevice, "triangle.vert.spv", 0, 0, 0, 0);
|
||||
if(vertexShader == NULL)
|
||||
{
|
||||
SDL_Log("Could not create vertex shader!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fragShader = loadShader(GPUDevice, "color.frag.spv", 0, 0, 0, 0);
|
||||
if(fragShader == NULL)
|
||||
{
|
||||
SDL_Log("Could not create fragment shader!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Creating the pipelines
|
||||
SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = {
|
||||
.target_info = {
|
||||
.num_color_targets = 1,
|
||||
.color_target_descriptions = (SDL_GPUColorTargetDescription[]){{
|
||||
.format = SDL_GetGPUSwapchainTextureFormat(GPUDevice, window)
|
||||
}},
|
||||
},
|
||||
.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
|
||||
.vertex_shader = vertexShader,
|
||||
.fragment_shader = fragShader,
|
||||
};
|
||||
|
||||
pipelineCreateInfo.rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL;
|
||||
pipeline = SDL_CreateGPUGraphicsPipeline(GPUDevice, &pipelineCreateInfo);
|
||||
if(pipeline == NULL) {
|
||||
SDL_Log("Could not create pipeline");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Free up shaders that are now bound to pipeline
|
||||
SDL_ReleaseGPUShader(GPUDevice, vertexShader);
|
||||
SDL_ReleaseGPUShader(GPUDevice, fragShader);
|
||||
|
||||
// Now to loop
|
||||
while (!done) {
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_EVENT_QUIT) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get our command buffer
|
||||
commandBuf = SDL_AcquireGPUCommandBuffer(GPUDevice);
|
||||
if(commandBuf == NULL) {
|
||||
SDL_Log("Could not get command buf!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get our swapchain
|
||||
if(!SDL_WaitAndAcquireGPUSwapchainTexture(commandBuf, window, &swapchainTexture, NULL, NULL)) {
|
||||
SDL_Log("Could not create swapchain!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Handle the swapchain
|
||||
if(swapchainTexture != NULL) {
|
||||
// Clear (background) color
|
||||
SDL_GPUColorTargetInfo colorInfo = {
|
||||
.texture = swapchainTexture,
|
||||
.clear_color = (SDL_FColor){0.25f, 0.5f, 0.1f, 1.0f},
|
||||
.load_op = SDL_GPU_LOADOP_CLEAR,
|
||||
.store_op = SDL_GPU_STOREOP_STORE
|
||||
};
|
||||
|
||||
// Now for the render pass
|
||||
renderPass = SDL_BeginGPURenderPass(commandBuf, &colorInfo, 1, NULL);
|
||||
SDL_BindGPUGraphicsPipeline(renderPass, pipeline);
|
||||
SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0);
|
||||
SDL_EndGPURenderPass(renderPass);
|
||||
} else {
|
||||
SDL_Log("Swapchain texture just does not exist! %s", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_SubmitGPUCommandBuffer(commandBuf);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
SDL_ReleaseGPUGraphicsPipeline(GPUDevice, pipeline);
|
||||
|
||||
SDL_ReleaseWindowFromGPUDevice(GPUDevice, window);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_DestroyGPUDevice(GPUDevice);
|
||||
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
13
shaders/color.frag
Normal file
13
shaders/color.frag
Normal file
@ -0,0 +1,13 @@
|
||||
#version 450
|
||||
|
||||
// layout(location = 0) in vec4 in_var_TEXCOORD0;
|
||||
// layout(location = 0) out vec4 out_var_SV_Target0;
|
||||
|
||||
layout(location = 0) in vec4 inColor;
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
outColor = inColor;
|
||||
}
|
||||
|
||||
42
shaders/triangle.vert
Normal file
42
shaders/triangle.vert
Normal file
@ -0,0 +1,42 @@
|
||||
#version 450
|
||||
|
||||
vec2 temp_pos;
|
||||
vec4 temp_color;
|
||||
|
||||
// layout(location = 0) out vec4 out_var_TEXCOORD0;
|
||||
layout(location = 0) out vec4 outColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color;
|
||||
vec2 pos;
|
||||
|
||||
if (uint(gl_VertexIndex) == 0u)
|
||||
{
|
||||
color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
pos = vec2(-0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec4 vert_color;
|
||||
vec2 vert_pos;
|
||||
if (uint(gl_VertexIndex) == 1u)
|
||||
{
|
||||
vert_color = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
vert_pos = vec2(0.5, -0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool index_exists = uint(gl_VertexIndex) == 2u;
|
||||
vert_color = mix(temp_color, vec4(0.0, 0.0, 1.0, 1.0), bvec4(index_exists));
|
||||
vert_pos = mix(temp_pos, vec2(0.0, 0.5), bvec2(index_exists));
|
||||
}
|
||||
color = vert_color;
|
||||
pos = vert_pos;
|
||||
}
|
||||
|
||||
// out_var_TEXCOORD0 = color;
|
||||
outColor = color;
|
||||
gl_Position = vec4(pos, 0.0, 1.0);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user