-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
efae5d6
commit b8959f7
Showing
11 changed files
with
366 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
/* | ||
* Vulkan Example - Example for using printf in shaders to help debugging. Can be used in conjunction with a debugging app like RenderDoc (https://renderdoc.org) | ||
* | ||
* See this whitepaper for details: https://www.lunarg.com/wp-content/uploads/2021/08/Using-Debug-Printf-02August2021.pdf | ||
* | ||
* Copyright (C) 2023 by Sascha Willems - www.saschawillems.de | ||
* | ||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) | ||
*/ | ||
|
||
/* | ||
* The only change required for printf in shaders on the application is enabling the VK_KHR_shader_non_semantic_info extensions | ||
* The actual printing is done in the shaders (see toon.vert from the glsl/hlsl) folder | ||
* For glsl shaders that use this feature, the GL_EXT_debug_printf extension needs to be enabled | ||
*/ | ||
|
||
#include "vulkanexamplebase.h" | ||
#include "VulkanglTFModel.h" | ||
|
||
#define ENABLE_VALIDATION false | ||
|
||
class VulkanExample : public VulkanExampleBase | ||
{ | ||
public: | ||
vks::Buffer uniformBuffer; | ||
vkglTF::Model scene; | ||
|
||
struct UBOVS { | ||
glm::mat4 projection; | ||
glm::mat4 model; | ||
glm::vec4 lightPos = glm::vec4(0.0f, 5.0f, 15.0f, 1.0f); | ||
} uboVS; | ||
|
||
VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; | ||
VkPipeline pipeline{ VK_NULL_HANDLE }; | ||
VkDescriptorSetLayout descriptorSetLayout{ VK_NULL_HANDLE }; | ||
VkDescriptorSet descriptorSet{ VK_NULL_HANDLE }; | ||
|
||
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION) | ||
{ | ||
title = "Debug output with shader printf"; | ||
camera.setRotation(glm::vec3(-4.35f, 16.25f, 0.0f)); | ||
camera.setRotationSpeed(0.5f); | ||
camera.setPosition(glm::vec3(0.1f, 1.1f, -8.5f)); | ||
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f); | ||
|
||
// Using printf requires the non semantic info extension to be enabled | ||
enabledDeviceExtensions.push_back(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); | ||
} | ||
|
||
~VulkanExample() | ||
{ | ||
// Note : Inherited destructor cleans up resources stored in base class | ||
vkDestroyPipeline(device, pipeline, nullptr); | ||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); | ||
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); | ||
uniformBuffer.destroy(); | ||
} | ||
|
||
void loadAssets() | ||
{ | ||
scene.loadFromFile(getAssetPath() + "models/treasure_smooth.gltf", vulkanDevice, queue, vkglTF::FileLoadingFlags::PreTransformVertices | vkglTF::FileLoadingFlags::PreMultiplyVertexColors | vkglTF::FileLoadingFlags::FlipY); | ||
} | ||
|
||
void buildCommandBuffers() | ||
{ | ||
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); | ||
VkClearValue clearValues[2]; | ||
|
||
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) | ||
{ | ||
VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo)); | ||
|
||
clearValues[0].color = defaultClearColor; | ||
clearValues[1].depthStencil = { 1.0f, 0 }; | ||
|
||
VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo(); | ||
renderPassBeginInfo.renderPass = renderPass; | ||
renderPassBeginInfo.framebuffer = frameBuffers[i]; | ||
renderPassBeginInfo.renderArea.extent.width = width; | ||
renderPassBeginInfo.renderArea.extent.height = height; | ||
renderPassBeginInfo.clearValueCount = 2; | ||
renderPassBeginInfo.pClearValues = clearValues; | ||
|
||
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); | ||
VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f); | ||
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport); | ||
VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0); | ||
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor); | ||
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr); | ||
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); | ||
scene.draw(drawCmdBuffers[i]); | ||
drawUI(drawCmdBuffers[i]); | ||
vkCmdEndRenderPass(drawCmdBuffers[i]); | ||
VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i])); | ||
} | ||
} | ||
|
||
void setupDescriptors() | ||
{ | ||
// Pool | ||
std::vector<VkDescriptorPoolSize> poolSizes = { | ||
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1), | ||
}; | ||
VkDescriptorPoolCreateInfo descriptorPoolInfo = vks::initializers::descriptorPoolCreateInfo(poolSizes, 1); | ||
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); | ||
|
||
// Layout | ||
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = { | ||
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), | ||
}; | ||
VkDescriptorSetLayoutCreateInfo descriptorLayout = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings); | ||
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout)); | ||
|
||
// Set | ||
VkDescriptorSetAllocateInfo allocInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayout, 1); | ||
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet)); | ||
std::vector<VkWriteDescriptorSet> writeDescriptorSets = { | ||
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor), | ||
}; | ||
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr); | ||
} | ||
|
||
void preparePipelines() | ||
{ | ||
// Layout | ||
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); | ||
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); | ||
|
||
// Pipeline | ||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); | ||
VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); | ||
VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); | ||
VkPipelineColorBlendStateCreateInfo colorBlendStateCI = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState); | ||
VkPipelineDepthStencilStateCreateInfo depthStencilStateCI = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL); | ||
VkPipelineViewportStateCreateInfo viewportStateCI = vks::initializers::pipelineViewportStateCreateInfo(1, 1, 0); | ||
VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT, 0); | ||
std::vector<VkDynamicState> dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; | ||
VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables); | ||
std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages; | ||
|
||
VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass); | ||
pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; | ||
pipelineCI.pRasterizationState = &rasterizationStateCI; | ||
pipelineCI.pColorBlendState = &colorBlendStateCI; | ||
pipelineCI.pMultisampleState = &multisampleStateCI; | ||
pipelineCI.pViewportState = &viewportStateCI; | ||
pipelineCI.pDepthStencilState = &depthStencilStateCI; | ||
pipelineCI.pDynamicState = &dynamicStateCI; | ||
pipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size()); | ||
pipelineCI.pStages = shaderStages.data(); | ||
pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({vkglTF::VertexComponent::Position, vkglTF::VertexComponent::Normal, vkglTF::VertexComponent::Color}); | ||
|
||
// Toon shading pipeline | ||
shaderStages[0] = loadShader(getShadersPath() + "debugprintf/toon.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); | ||
shaderStages[1] = loadShader(getShadersPath() + "debugprintf/toon.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); | ||
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCI, nullptr, &pipeline)); | ||
} | ||
|
||
// Prepare and initialize uniform buffer containing shader uniforms | ||
void prepareUniformBuffers() | ||
{ | ||
VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(uboVS))); | ||
VK_CHECK_RESULT(uniformBuffer.map()); | ||
} | ||
|
||
void updateUniformBuffers() | ||
{ | ||
uboVS.projection = camera.matrices.perspective; | ||
uboVS.model = camera.matrices.view; | ||
memcpy(uniformBuffer.mapped, &uboVS, sizeof(uboVS)); | ||
} | ||
|
||
void draw() | ||
{ | ||
VulkanExampleBase::prepareFrame(); | ||
submitInfo.commandBufferCount = 1; | ||
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; | ||
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); | ||
VulkanExampleBase::submitFrame(); | ||
} | ||
|
||
void prepare() | ||
{ | ||
VulkanExampleBase::prepare(); | ||
loadAssets(); | ||
prepareUniformBuffers(); | ||
setupDescriptors(); | ||
preparePipelines(); | ||
buildCommandBuffers(); | ||
prepared = true; | ||
} | ||
|
||
virtual void render() | ||
{ | ||
if (!prepared) | ||
return; | ||
updateUniformBuffers(); | ||
draw(); | ||
} | ||
|
||
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay) | ||
{ | ||
if (overlay->header("Info")) { | ||
overlay->text("Please run this sample with a graphics debugger attached"); | ||
} | ||
} | ||
}; | ||
|
||
VULKAN_EXAMPLE_MAIN() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#version 450 | ||
|
||
layout (binding = 1) uniform sampler2D samplerColorMap; | ||
|
||
layout (location = 0) in vec3 inNormal; | ||
layout (location = 1) in vec3 inColor; | ||
layout (location = 2) in vec3 inViewVec; | ||
layout (location = 3) in vec3 inLightVec; | ||
|
||
layout (location = 0) out vec4 outFragColor; | ||
|
||
void main() | ||
{ | ||
// Desaturate color | ||
vec3 color = vec3(mix(inColor, vec3(dot(vec3(0.2126,0.7152,0.0722), inColor)), 0.65)); | ||
|
||
// High ambient colors because mesh materials are pretty dark | ||
vec3 ambient = color * vec3(1.0); | ||
vec3 N = normalize(inNormal); | ||
vec3 L = normalize(inLightVec); | ||
vec3 V = normalize(inViewVec); | ||
vec3 R = reflect(-L, N); | ||
vec3 diffuse = max(dot(N, L), 0.0) * color; | ||
vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.75); | ||
outFragColor = vec4(ambient + diffuse * 1.75 + specular, 1.0); | ||
|
||
float intensity = dot(N,L); | ||
float shade = 1.0; | ||
shade = intensity < 0.5 ? 0.75 : shade; | ||
shade = intensity < 0.35 ? 0.6 : shade; | ||
shade = intensity < 0.25 ? 0.5 : shade; | ||
shade = intensity < 0.1 ? 0.25 : shade; | ||
|
||
outFragColor.rgb = inColor * 3.0 * shade; | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#version 450 | ||
|
||
// This extension is required to use printf | ||
#extension GL_EXT_debug_printf : enable | ||
|
||
layout (location = 0) in vec3 inPos; | ||
layout (location = 1) in vec3 inNormal; | ||
layout (location = 2) in vec3 inColor; | ||
|
||
layout (binding = 0) uniform UBO | ||
{ | ||
mat4 projection; | ||
mat4 model; | ||
vec4 lightPos; | ||
} ubo; | ||
|
||
layout (location = 0) out vec3 outNormal; | ||
layout (location = 1) out vec3 outColor; | ||
layout (location = 2) out vec3 outViewVec; | ||
layout (location = 3) out vec3 outLightVec; | ||
|
||
void main() | ||
{ | ||
outNormal = inNormal; | ||
outColor = inColor; | ||
gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0); | ||
|
||
vec4 pos = ubo.model * vec4(inPos, 1.0); | ||
|
||
// Output the vertex position using debug printf | ||
debugPrintfEXT("Position = %v4f", pos); | ||
|
||
outNormal = mat3(ubo.model) * inNormal; | ||
vec3 lPos = mat3(ubo.model) * ubo.lightPos.xyz; | ||
outLightVec = lPos - pos.xyz; | ||
outViewVec = -pos.xyz; | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
Texture2D textureColorMap : register(t1); | ||
SamplerState samplerColorMap : register(s1); | ||
|
||
struct VSOutput | ||
{ | ||
[[vk::location(0)]] float3 Normal : NORMAL0; | ||
[[vk::location(1)]] float3 Color : COLOR0; | ||
[[vk::location(2)]] float3 ViewVec : TEXCOORD1; | ||
[[vk::location(3)]] float3 LightVec : TEXCOORD2; | ||
}; | ||
|
||
float4 main(VSOutput input) : SV_TARGET | ||
{ | ||
// Desaturate color | ||
float3 color = float3(lerp(input.Color, dot(float3(0.2126,0.7152,0.0722), input.Color).xxx, 0.65)); | ||
|
||
// High ambient colors because mesh materials are pretty dark | ||
float3 ambient = color * float3(1.0, 1.0, 1.0); | ||
float3 N = normalize(input.Normal); | ||
float3 L = normalize(input.LightVec); | ||
float3 V = normalize(input.ViewVec); | ||
float3 R = reflect(-L, N); | ||
float3 diffuse = max(dot(N, L), 0.0) * color; | ||
float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); | ||
|
||
float intensity = dot(N,L); | ||
float shade = 1.0; | ||
shade = intensity < 0.5 ? 0.75 : shade; | ||
shade = intensity < 0.35 ? 0.6 : shade; | ||
shade = intensity < 0.25 ? 0.5 : shade; | ||
shade = intensity < 0.1 ? 0.25 : shade; | ||
|
||
return float4(input.Color * 3.0 * shade, 1); | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
struct VSInput | ||
{ | ||
[[vk::location(0)]] float3 Pos : POSITION0; | ||
[[vk::location(1)]] float3 Normal : NORMAL0; | ||
[[vk::location(2)]] float3 Color : COLOR0; | ||
}; | ||
|
||
struct UBO | ||
{ | ||
float4x4 projection; | ||
float4x4 model; | ||
float4 lightPos; | ||
}; | ||
|
||
cbuffer ubo : register(b0) { UBO ubo; } | ||
|
||
struct VSOutput | ||
{ | ||
float4 Pos : SV_POSITION; | ||
[[vk::location(0)]] float3 Normal : NORMAL0; | ||
[[vk::location(1)]] float3 Color : COLOR0; | ||
[[vk::location(2)]] float3 ViewVec : TEXCOORD1; | ||
[[vk::location(3)]] float3 LightVec : TEXCOORD2; | ||
}; | ||
|
||
VSOutput main(VSInput input) | ||
{ | ||
VSOutput output = (VSOutput)0; | ||
output.Normal = input.Normal; | ||
output.Color = input.Color; | ||
output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); | ||
|
||
float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); | ||
// Output the vertex position using debug printf | ||
printf("Position = %v4f", pos); | ||
|
||
output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; | ||
float3 lPos = mul((float4x3)ubo.model, ubo.lightPos.xyz).xyz; | ||
output.LightVec = lPos - pos.xyz; | ||
output.ViewVec = -pos.xyz; | ||
return output; | ||
} |
Binary file not shown.