diff --git a/app/src/main/cpp/skyline/gpu/shader_manager.cpp b/app/src/main/cpp/skyline/gpu/shader_manager.cpp index fa237c10..61dfe6ec 100644 --- a/app/src/main/cpp/skyline/gpu/shader_manager.cpp +++ b/app/src/main/cpp/skyline/gpu/shader_manager.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "shader_manager.h" namespace Shader::Log { @@ -75,4 +77,73 @@ namespace skyline::gpu { }, }; } + + /** + * @brief A shader environment for all graphics pipeline stages + */ + class GraphicsEnvironment : public Shader::Environment { + private: + std::vector binary; + u32 baseOffset; + + public: + explicit GraphicsEnvironment(std::vector pBinary, u32 baseOffset, Shader::Stage pStage) : binary(std::move(pBinary)), baseOffset(baseOffset) { + sph = *reinterpret_cast(binary.data()); + start_address = baseOffset; + stage = pStage; + } + + [[nodiscard]] u64 ReadInstruction(u32 address) final { + address -= baseOffset; + if (binary.size() < (address + sizeof(u64))) + throw exception("Out of bounds instruction read: 0x{:X}", address); + return *reinterpret_cast(binary.data() + address); + } + + [[nodiscard]] u32 ReadCbufValue(u32 cbuf_index, u32 cbuf_offset) final { + throw exception("Not implemented"); + } + + [[nodiscard]] Shader::TextureType ReadTextureType(u32 raw_handle) final { + throw exception("Not implemented"); + } + + [[nodiscard]] u32 TextureBoundBuffer() const final { + throw exception("Not implemented"); + } + + [[nodiscard]] u32 LocalMemorySize() const final { + return static_cast(sph.LocalMemorySize()) + sph.common3.shader_local_memory_crs_size; + } + + [[nodiscard]] u32 SharedMemorySize() const final { + return 0; // Shared memory size is only relevant for compute shaders + } + + [[nodiscard]] std::array WorkgroupSize() const final { + return {0, 0, 0}; // Workgroup size is only relevant for compute shaders + } + }; + + vk::raii::ShaderModule ShaderManager::CompileGraphicsShader(const std::vector &binary, Shader::Stage stage, u32 baseOffset, Shader::RuntimeInfo& runtimeInfo) { + GraphicsEnvironment environment{binary, baseOffset, stage}; + Shader::Maxwell::Flow::CFG cfg(environment, flowBlockPool, Shader::Maxwell::Location{static_cast(baseOffset + sizeof(Shader::ProgramHeader))}); + + auto program{Shader::Maxwell::TranslateProgram(instPool, blockPool, environment, cfg, hostTranslateInfo)}; + + Shader::Backend::Bindings bindings{}; + auto spirv{Shader::Backend::SPIRV::EmitSPIRV(profile, runtimeInfo, program, bindings)}; + + runtimeInfo.previous_stage_stores = program.info.stores; + if (program.is_geometry_passthrough) + runtimeInfo.previous_stage_stores.mask |= program.info.passthrough.mask; + + vk::ShaderModuleCreateInfo createInfo{ + .pCode = spirv.data(), + .codeSize = spirv.size() * sizeof(u32), + }; + vk::raii::ShaderModule shaderModule(gpu.vkDevice, createInfo); + + return shaderModule; + } } diff --git a/app/src/main/cpp/skyline/gpu/shader_manager.h b/app/src/main/cpp/skyline/gpu/shader_manager.h index 06d775d0..f0005783 100644 --- a/app/src/main/cpp/skyline/gpu/shader_manager.h +++ b/app/src/main/cpp/skyline/gpu/shader_manager.h @@ -4,6 +4,11 @@ #pragma once #include +#include +#include +#include +#include +#include #include #include #include @@ -15,10 +20,18 @@ namespace skyline::gpu { class ShaderManager { private: GPU &gpu; + Shader::ObjectPool flowBlockPool; + Shader::ObjectPool instPool; + Shader::ObjectPool blockPool; Shader::HostTranslateInfo hostTranslateInfo; Shader::Profile profile; public: ShaderManager(const DeviceState& state, GPU &gpu); + + /** + * @note `runtimeInfo::previous_stage_stores` will automatically be updated for the next stage + */ + vk::raii::ShaderModule CompileGraphicsShader(const std::vector &binary, Shader::Stage stage, u32 baseOffset, Shader::RuntimeInfo& runtimeInfo); }; }