#include "PaintLayerNode.h" #include "../GPU.h" #include SDL_GPUSampler* PaintLayerNode::sampler = nullptr; GPUBuffer* PaintLayerNode::vertexBuffer = nullptr; void PaintLayerNode::setupPipeline() { // TODO: abstract this too, but not as important as the Graphics plr_pipeline SDL_GPUSamplerCreateInfo samplerInfo = {}; samplerInfo.min_filter = SDL_GPU_FILTER_LINEAR; samplerInfo.mag_filter = SDL_GPU_FILTER_LINEAR; samplerInfo.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR; samplerInfo.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; samplerInfo.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; samplerInfo.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; samplerInfo.mip_lod_bias = 0.0f; samplerInfo.max_anisotropy = 1.0f; samplerInfo.compare_op = SDL_GPU_COMPAREOP_NEVER; samplerInfo.min_lod = 0.0f; samplerInfo.max_lod = 1000.0f; sampler = SDL_CreateGPUSampler(GPU::GetDevice(), &samplerInfo); if (!sampler) { throw std::runtime_error(SDL_GetError()); } // diabolical copypaste from CanvasAppLayer float previewVertices[16]; SDL_FRect fullRect = { 0.0f, 0.0f, 1.0f, 1.0f }; SDL_FRect previewRect = { 0.0f, 0.0f, 1.0f, 1.0f }; #define NDC_TO_SCREEN * 2.0f - 1.0f // parameters are using screen space // bottom left previewVertices[0] = (previewRect.x - fullRect.x) / fullRect.w NDC_TO_SCREEN; previewVertices[1] = (previewRect.y - fullRect.y) / fullRect.h NDC_TO_SCREEN; previewVertices[2] = (previewRect.x - fullRect.x) / fullRect.w; // match 0 previewVertices[3] = (previewRect.y - fullRect.y) / fullRect.h; // match 13 // bottom right previewVertices[4] = (previewRect.x + previewRect.w - fullRect.x) / fullRect.w NDC_TO_SCREEN; previewVertices[5] = (previewRect.y - fullRect.y) / fullRect.h NDC_TO_SCREEN; previewVertices[6] = (previewRect.x + previewRect.w - fullRect.x) / fullRect.w; // match 4 previewVertices[7] = (previewRect.y - fullRect.y) / fullRect.h; // match 13 // top left previewVertices[8] = (previewRect.x - fullRect.x) / fullRect.w NDC_TO_SCREEN; previewVertices[9] = (previewRect.y + previewRect.h - fullRect.y) / fullRect.h NDC_TO_SCREEN; previewVertices[10] = (previewRect.x - fullRect.x) / fullRect.w; // match 8 previewVertices[11] = (previewRect.y + previewRect.h - fullRect.y) / fullRect.h; // match 1 // top right previewVertices[12] = (previewRect.x + previewRect.w - fullRect.x) / fullRect.w NDC_TO_SCREEN; previewVertices[13] = (previewRect.y + previewRect.h - fullRect.y) / fullRect.h NDC_TO_SCREEN; previewVertices[14] = (previewRect.x + previewRect.w - fullRect.x) / fullRect.w; // match 12 previewVertices[15] = (previewRect.y + previewRect.h - fullRect.y) / fullRect.h; // match 1 // invert y for (int i = 1; i < 16; i += 4) { previewVertices[i] = -1.0f * previewVertices[i]; } #undef NDC_TO_SCREEN SDL_GPUBufferCreateInfo buf_info = { .usage = SDL_GPU_BUFFERUSAGE_VERTEX, .size = sizeof(previewVertices), .props = {} }; vertexBuffer = new GPUBuffer(&buf_info); if (!vertexBuffer) { throw std::runtime_error(SDL_GetError()); } vertexBuffer->Transfer(previewVertices); } PaintLayerNode::PaintLayerNode() { if (!vertexBuffer) { setupPipeline(); } } PaintLayerNode::~PaintLayerNode() { delete Target; } void PaintLayerNode::Composite(Texture* target) { GPU::AquirePushCommandBuffer(); GraphicsPipeline* pipeline = BlendingPipelineManagementContext::GetPipeline(BlendMode); GPU::SubmitCommandsPopCommandBuffer(); SDL_GPUViewport viewport = {}; viewport.x = 0; viewport.y = 0; viewport.w = (float)target->GetWidth(); viewport.h = (float)target->GetHeight(); SDL_GPUColorTargetInfo colorTarget = {}; colorTarget.texture = target->Get(); colorTarget.clear_color = { 0.0f, 0.0f, 0.0f, 0.0f }; colorTarget.load_op = SDL_GPU_LOADOP_LOAD; colorTarget.store_op = SDL_GPU_STOREOP_STORE; colorTarget.mip_level = 0; colorTarget.layer_or_depth_plane = 0; colorTarget.cycle = false; GPU::AquirePushCommandBuffer(); GPU::BeginRendering({ &colorTarget }, nullptr); SDL_SetGPUViewport(GPU::GetRenderPass(), &viewport); pipeline->Bind(); SDL_GPUBufferBinding vertexBufferBinding = { .buffer = vertexBuffer->Get(), .offset = 0 }; SDL_BindGPUVertexBuffers(GPU::GetRenderPass(), 0, &vertexBufferBinding, 1); SDL_GPUTextureSamplerBinding textureSamplerBinding = { .texture = Target->Get(), .sampler = sampler }; SDL_BindGPUFragmentSamplers(GPU::GetRenderPass(), 0, &textureSamplerBinding, 1); float pushConstants[1] = { (float)Opacity }; SDL_PushGPUFragmentUniformData(GPU::GetCommandBuffer(), 0, pushConstants, sizeof(pushConstants)); SDL_DrawGPUPrimitives(GPU::GetRenderPass(), 4, 1, 0, 0); // draw canvas GPU::EndRendering(); GPU::SubmitCommandsPopCommandBuffer(); }