diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a5d585df9..780fd2eda 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -895,6 +895,7 @@ set( FASTMATH_SOURCES #Vulkan stuff must go into a separate list later because it needs to be disabled for some platforms rendering/vulkan/system/vk_device.cpp rendering/vulkan/system/vk_swapchain.cpp + rendering/vulkan/system/vk_builders.cpp rendering/vulkan/system/vk_framebuffer.cpp rendering/vulkan/textures/vk_samplers.cpp rendering/vulkan/textures/vk_hwtexture.cpp diff --git a/src/rendering/vulkan/system/vk_builders.cpp b/src/rendering/vulkan/system/vk_builders.cpp new file mode 100644 index 000000000..eb0f3ca57 --- /dev/null +++ b/src/rendering/vulkan/system/vk_builders.cpp @@ -0,0 +1,182 @@ + +#include "vk_builders.h" +#include "doomerrors.h" +#include +#include + +static const TBuiltInResource DefaultTBuiltInResource = { + /* .MaxLights = */ 32, + /* .MaxClipPlanes = */ 6, + /* .MaxTextureUnits = */ 32, + /* .MaxTextureCoords = */ 32, + /* .MaxVertexAttribs = */ 64, + /* .MaxVertexUniformComponents = */ 4096, + /* .MaxVaryingFloats = */ 64, + /* .MaxVertexTextureImageUnits = */ 32, + /* .MaxCombinedTextureImageUnits = */ 80, + /* .MaxTextureImageUnits = */ 32, + /* .MaxFragmentUniformComponents = */ 4096, + /* .MaxDrawBuffers = */ 32, + /* .MaxVertexUniformVectors = */ 128, + /* .MaxVaryingVectors = */ 8, + /* .MaxFragmentUniformVectors = */ 16, + /* .MaxVertexOutputVectors = */ 16, + /* .MaxFragmentInputVectors = */ 15, + /* .MinProgramTexelOffset = */ -8, + /* .MaxProgramTexelOffset = */ 7, + /* .MaxClipDistances = */ 8, + /* .MaxComputeWorkGroupCountX = */ 65535, + /* .MaxComputeWorkGroupCountY = */ 65535, + /* .MaxComputeWorkGroupCountZ = */ 65535, + /* .MaxComputeWorkGroupSizeX = */ 1024, + /* .MaxComputeWorkGroupSizeY = */ 1024, + /* .MaxComputeWorkGroupSizeZ = */ 64, + /* .MaxComputeUniformComponents = */ 1024, + /* .MaxComputeTextureImageUnits = */ 16, + /* .MaxComputeImageUniforms = */ 8, + /* .MaxComputeAtomicCounters = */ 8, + /* .MaxComputeAtomicCounterBuffers = */ 1, + /* .MaxVaryingComponents = */ 60, + /* .MaxVertexOutputComponents = */ 64, + /* .MaxGeometryInputComponents = */ 64, + /* .MaxGeometryOutputComponents = */ 128, + /* .MaxFragmentInputComponents = */ 128, + /* .MaxImageUnits = */ 8, + /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, + /* .MaxCombinedShaderOutputResources = */ 8, + /* .MaxImageSamples = */ 0, + /* .MaxVertexImageUniforms = */ 0, + /* .MaxTessControlImageUniforms = */ 0, + /* .MaxTessEvaluationImageUniforms = */ 0, + /* .MaxGeometryImageUniforms = */ 0, + /* .MaxFragmentImageUniforms = */ 8, + /* .MaxCombinedImageUniforms = */ 8, + /* .MaxGeometryTextureImageUnits = */ 16, + /* .MaxGeometryOutputVertices = */ 256, + /* .MaxGeometryTotalOutputComponents = */ 1024, + /* .MaxGeometryUniformComponents = */ 1024, + /* .MaxGeometryVaryingComponents = */ 64, + /* .MaxTessControlInputComponents = */ 128, + /* .MaxTessControlOutputComponents = */ 128, + /* .MaxTessControlTextureImageUnits = */ 16, + /* .MaxTessControlUniformComponents = */ 1024, + /* .MaxTessControlTotalOutputComponents = */ 4096, + /* .MaxTessEvaluationInputComponents = */ 128, + /* .MaxTessEvaluationOutputComponents = */ 128, + /* .MaxTessEvaluationTextureImageUnits = */ 16, + /* .MaxTessEvaluationUniformComponents = */ 1024, + /* .MaxTessPatchComponents = */ 120, + /* .MaxPatchVertices = */ 32, + /* .MaxTessGenLevel = */ 64, + /* .MaxViewports = */ 16, + /* .MaxVertexAtomicCounters = */ 0, + /* .MaxTessControlAtomicCounters = */ 0, + /* .MaxTessEvaluationAtomicCounters = */ 0, + /* .MaxGeometryAtomicCounters = */ 0, + /* .MaxFragmentAtomicCounters = */ 8, + /* .MaxCombinedAtomicCounters = */ 8, + /* .MaxAtomicCounterBindings = */ 1, + /* .MaxVertexAtomicCounterBuffers = */ 0, + /* .MaxTessControlAtomicCounterBuffers = */ 0, + /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, + /* .MaxGeometryAtomicCounterBuffers = */ 0, + /* .MaxFragmentAtomicCounterBuffers = */ 1, + /* .MaxCombinedAtomicCounterBuffers = */ 1, + /* .MaxAtomicCounterBufferSize = */ 16384, + /* .MaxTransformFeedbackBuffers = */ 4, + /* .MaxTransformFeedbackInterleavedComponents = */ 64, + /* .MaxCullDistances = */ 8, + /* .MaxCombinedClipAndCullDistances = */ 8, + /* .MaxSamples = */ 4, +// /* .maxMeshOutputVerticesNV = */ 256, +// /* .maxMeshOutputPrimitivesNV = */ 512, +// /* .maxMeshWorkGroupSizeX_NV = */ 32, +// /* .maxMeshWorkGroupSizeY_NV = */ 1, +// /* .maxMeshWorkGroupSizeZ_NV = */ 1, +// /* .maxTaskWorkGroupSizeX_NV = */ 32, +// /* .maxTaskWorkGroupSizeY_NV = */ 1, +// /* .maxTaskWorkGroupSizeZ_NV = */ 1, +// /* .maxMeshViewCountNV = */ 4, + + /* .limits = */ { + /* .nonInductiveForLoops = */ 1, + /* .whileLoops = */ 1, + /* .doWhileLoops = */ 1, + /* .generalUniformIndexing = */ 1, + /* .generalAttributeMatrixVectorIndexing = */ 1, + /* .generalVaryingIndexing = */ 1, + /* .generalSamplerIndexing = */ 1, + /* .generalVariableIndexing = */ 1, + /* .generalConstantMatrixVectorIndexing = */ 1, + } +}; + +ShaderBuilder::ShaderBuilder() +{ +} + +void ShaderBuilder::setVertexShader(const FString &c) +{ + code = c; + stage = EShLanguage::EShLangVertex; +} + +void ShaderBuilder::setFragmentShader(const FString &c) +{ + code = c; + stage = EShLanguage::EShLangFragment; +} + +std::unique_ptr ShaderBuilder::create(VulkanDevice *device) +{ + EShLanguage stage = (EShLanguage)this->stage; + const char *sources[] = { code.GetChars() }; + + TBuiltInResource resources = DefaultTBuiltInResource; + + glslang::TShader shader(stage); + shader.setStrings(sources, 1); + shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100); + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); + shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0); + bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules); + if (!compileSuccess) + { + I_FatalError("Shader compile failed: %s\n", shader.getInfoLog()); + } + + glslang::TProgram program; + program.addShader(&shader); + bool linkSuccess = program.link(EShMsgDefault); + if (!linkSuccess) + { + I_FatalError("Shader link failed: %s\n", program.getInfoLog()); + } + + glslang::TIntermediate *intermediate = program.getIntermediate(stage); + if (!intermediate) + { + throw std::runtime_error("Internal shader compiler error"); + } + + glslang::SpvOptions spvOptions; + spvOptions.generateDebugInfo = false; + spvOptions.disableOptimizer = false; + spvOptions.optimizeSize = false; + + std::vector spirv; + spv::SpvBuildLogger logger; + glslang::GlslangToSpv(*intermediate, spirv, &logger, &spvOptions); + + VkShaderModuleCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = spirv.size(); + createInfo.pCode = spirv.data(); + + VkShaderModule shaderModule; + VkResult result = vkCreateShaderModule(device->device, &createInfo, nullptr, &shaderModule); + if (result != VK_SUCCESS) + throw std::runtime_error("Could not create vulkan shader module"); + + return std::make_unique(device, shaderModule); +} diff --git a/src/rendering/vulkan/system/vk_builders.h b/src/rendering/vulkan/system/vk_builders.h index bab65073f..89f2e98ed 100644 --- a/src/rendering/vulkan/system/vk_builders.h +++ b/src/rendering/vulkan/system/vk_builders.h @@ -1,6 +1,7 @@ #pragma once #include "vk_objects.h" +#include "zstring.h" #include template @@ -95,6 +96,21 @@ private: VmaAllocationCreateInfo allocInfo = {}; }; +class ShaderBuilder +{ +public: + ShaderBuilder(); + + void setVertexShader(const FString &code); + void setFragmentShader(const FString &code); + + std::unique_ptr create(VulkanDevice *device); + +private: + FString code; + int stage; +}; + class ComputePipelineBuilder { public: diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index 97ebf03b8..05e9f8520 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -33,6 +33,10 @@ #include "vk_framebuffer.h" #include "vulkan/textures/vk_samplers.h" +#include "vulkan/system/vk_builders.h" +#include "doomerrors.h" + +#include EXTERN_CVAR(Bool, vid_vsync) EXTERN_CVAR(Bool, r_drawvoxels) @@ -41,8 +45,28 @@ EXTERN_CVAR(Int, gl_tonemap) VulkanFrameBuffer::VulkanFrameBuffer(void *hMonitor, bool fullscreen, VulkanDevice *dev) : Super(hMonitor, fullscreen) { + ShInitialize(); + //screen = this; // temporary hack to make the tutorial code work. +#if 0 + { + const char *lumpName = "shaders/glsl/screenquad.vp"; + int lump = Wads.CheckNumForFullName(lumpName, 0); + if (lump == -1) I_FatalError("Unable to load '%s'", lumpName); + FString code = Wads.ReadLump(lump).GetString().GetChars(); + + FString patchedCode; + patchedCode.AppendFormat("#version %d\n", 450); + patchedCode << "#line 1\n"; + patchedCode << code; + + ShaderBuilder builder; + builder.setVertexShader(patchedCode); + auto shader = builder.create(dev); + } +#endif + device = dev; mSamplerManager = new VkSamplerManager(device); SetViewportRects(nullptr); @@ -51,6 +75,7 @@ VulkanFrameBuffer::VulkanFrameBuffer(void *hMonitor, bool fullscreen, VulkanDevi VulkanFrameBuffer::~VulkanFrameBuffer() { delete mSamplerManager; + ShFinalize(); } void VulkanFrameBuffer::InitializeState()