Implement enough of a ray query raytracer that it at least outputs something

This commit is contained in:
Magnus Norddahl 2022-07-03 01:47:11 +02:00
parent 12ffde80bc
commit 65445a7b07
8 changed files with 188 additions and 74 deletions

View file

@ -46,8 +46,16 @@ layout(push_constant) uniform PushConstants
{
uint LightStart;
uint LightEnd;
int surfaceIndex;
int pushPadding;
int SurfaceIndex;
int PushPadding1;
vec2 TileTL;
vec2 TileBR;
vec3 LightmapOrigin;
float PushPadding2;
vec3 LightmapStepX;
float PushPadding3;
vec3 LightmapStepY;
float PushPadding4;
};
layout(location = 0) in vec3 worldpos;
@ -59,12 +67,13 @@ void main()
vec3 origin = worldpos;
vec3 normal;
if (surfaceIndex >= 0)
if (SurfaceIndex >= 0)
{
normal = surfaces[surfaceIndex].Normal;
normal = surfaces[SurfaceIndex].Normal;
origin += normal * 0.1;
}
vec3 incoming = vec3(0.0);
for (uint j = LightStart; j < LightEnd; j++)
{
LightInfo light = lights[j];
@ -76,7 +85,7 @@ void main()
float distAttenuation = max(1.0 - (dist / light.Radius), 0.0);
float angleAttenuation = 1.0f;
if (surfaceIndex >= 0)
if (SurfaceIndex >= 0)
{
angleAttenuation = max(dot(normal, dir), 0.0);
}
@ -98,13 +107,13 @@ void main()
if (rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT)
{
incoming.rgb += light.Color * (attenuation * light.Intensity) * incoming.w;
incoming.rgb += light.Color * (attenuation * light.Intensity);
}
}
}
}
fragcolor = vec4(0.0);
fragcolor = vec4(incoming, 1.0);
}
)glsl";

View file

@ -2,20 +2,20 @@ static const char* glsl_vert = R"glsl(
#version 460
layout(set = 0, binding = 1) uniform Uniforms
{
vec3 SunDir;
float Padding1;
vec3 SunColor;
float SunIntensity;
};
layout(push_constant) uniform PushConstants
{
uint LightStart;
uint LightEnd;
int surfaceIndex;
int pushPadding;
int SurfaceIndex;
int PushPadding1;
vec2 TileTL;
vec2 TileBR;
vec3 LightmapOrigin;
float PushPadding2;
vec3 LightmapStepX;
float PushPadding3;
vec3 LightmapStepY;
float PushPadding4;
};
layout(location = 0) out vec3 worldpos;
@ -29,8 +29,9 @@ vec2 positions[4] = vec2[](
void main()
{
worldpos = vec3(0.0);
gl_Position = vec4(positions[gl_VertexIndex] * 2.0 - 1.0, 0.0, 1.0);
vec2 tilepos = positions[gl_VertexIndex];
worldpos = LightmapOrigin + LightmapStepX * tilepos.x + LightmapStepY * tilepos.y;
gl_Position = vec4(mix(TileTL, TileBR, tilepos) * 2.0 - 1.0, 0.0, 1.0);
}
)glsl";

View file

@ -42,7 +42,77 @@ void GPURaytracer2::Raytrace(LevelMesh* level)
printf("Ray tracing in progress...\n");
BeginCommands();
std::vector<LightmapImage> surfaceImages;
for (size_t i = 0; i < mesh->surfaces.size(); i++)
{
Surface* surface = mesh->surfaces[i].get();
int sampleWidth = surface->lightmapDims[0];
int sampleHeight = surface->lightmapDims[1];
LightmapImage img = CreateImage(sampleWidth, sampleHeight);
RenderPassBegin()
.RenderPass(renderPass.get())
.RenderArea(0, 0, sampleWidth, sampleHeight)
.Framebuffer(img.Framebuffer.get())
.Execute(cmdbuffer.get());
PushConstants2 pc;
pc.LightStart = 0;
pc.LightEnd = mesh->map->ThingLights.Size();
pc.SurfaceIndex = (int32_t)i;
pc.TileTL = vec2(0.0f);
pc.TileBR = vec2(1.0f);
pc.LightmapOrigin = surface->lightmapOrigin;
pc.LightmapStepX = surface->lightmapSteps[0] * (float)sampleWidth;
pc.LightmapStepY = surface->lightmapSteps[1] * (float)sampleHeight;
VkViewport viewport = {};
viewport.maxDepth = 1;
viewport.width = (float)sampleWidth;
viewport.height = (float)sampleHeight;
cmdbuffer->setViewport(0, 1, &viewport);
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0, descriptorSet.get());
cmdbuffer->pushConstants(pipelineLayout.get(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants2), &pc);
cmdbuffer->draw(4, 1, 0, 0);
cmdbuffer->endRenderPass();
PipelineBarrier()
.AddImage(img.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT)
.Execute(cmdbuffer.get(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
VkBufferImageCopy region = {};
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.layerCount = 1;
region.imageExtent.width = sampleWidth;
region.imageExtent.height = sampleHeight;
region.imageExtent.depth = 1;
cmdbuffer->copyImageToBuffer(img.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img.Transfer->buffer, 1, &region);
surfaceImages.push_back(std::move(img));
}
FinishCommands();
for (size_t i = 0; i < mesh->surfaces.size(); i++)
{
Surface* surface = mesh->surfaces[i].get();
int sampleWidth = surface->lightmapDims[0];
int sampleHeight = surface->lightmapDims[1];
vec4* pixels = (vec4*)surfaceImages[i].Transfer->Map(0, sampleWidth * sampleHeight * sizeof(vec4));
for (int i = 0; i < sampleWidth * sampleHeight; i++)
{
surface->samples[i] = pixels[i].xyz();
}
surfaceImages[i].Transfer->Unmap();
}
if (device->renderdoc)
device->renderdoc->EndFrameCapture(0, 0);
@ -62,7 +132,6 @@ void GPURaytracer2::CreateVulkanObjects()
CreateTopLevelAccelerationStructure();
CreateShaders();
CreatePipeline();
CreateFrameBuffer();
CreateDescriptorSet();
PipelineBarrier()
@ -334,9 +403,10 @@ void GPURaytracer2::CreatePipeline()
{
descriptorSetLayout = DescriptorSetLayoutBuilder()
.AddBinding(0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
.DebugName("descriptorSetLayout")
.Create(device.get());
@ -348,19 +418,19 @@ void GPURaytracer2::CreatePipeline()
renderPass = RenderPassBuilder()
.AddAttachment(
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_R32G32B32A32_SFLOAT,
VK_SAMPLE_COUNT_1_BIT,
VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VK_ATTACHMENT_STORE_OP_STORE,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
.AddSubpass()
.AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
.AddExternalSubpassDependency(
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT)
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT)
.DebugName("renderpass")
.Create(device.get());
@ -370,35 +440,43 @@ void GPURaytracer2::CreatePipeline()
.AddVertexShader(vertShader.get())
.AddFragmentShader(fragShader.get())
.Topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
.Viewport(0.0f, 0.0f, 320.0f, 200.0f)
.Scissor(0, 0, 320, 200)
.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT)
.Viewport(0.0f, 0.0f, 0.0f, 0.0f)
.Scissor(0, 0, 4096, 4096)
.DebugName("pipeline")
.Create(device.get());
}
void GPURaytracer2::CreateFrameBuffer()
LightmapImage GPURaytracer2::CreateImage(int width, int height)
{
framebufferImage = ImageBuilder()
LightmapImage img;
img.Image = ImageBuilder()
.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
.Format(VK_FORMAT_R8G8B8A8_UNORM)
.Size(320, 200)
.Format(VK_FORMAT_R32G32B32A32_SFLOAT)
.Size(width, height)
.DebugName("LightmapImage.Image")
.Create(device.get());
framebufferImageView = ImageViewBuilder()
.Image(framebufferImage.get(), VK_FORMAT_R8G8B8A8_UNORM)
.DebugName("framebufferImageView")
img.View = ImageViewBuilder()
.Image(img.Image.get(), VK_FORMAT_R32G32B32A32_SFLOAT)
.DebugName("LightmapImage.View")
.Create(device.get());
framebuffer = FramebufferBuilder()
img.Framebuffer = FramebufferBuilder()
.RenderPass(renderPass.get())
.Size(320, 200)
.AddAttachment(framebufferImageView.get())
.DebugName("framebuffer")
.Size(width, height)
.AddAttachment(img.View.get())
.DebugName("LightmapImage.Framebuffer")
.Create(device.get());
PipelineBarrier()
.AddImage(framebufferImage.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
.Execute(cmdbuffer.get(), 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
img.Transfer = BufferBuilder()
.Size(width * height * sizeof(vec4))
.Usage(VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
.DebugName("LightmapImage.Transfer")
.Create(device.get());
return img;
}
void GPURaytracer2::CreateDescriptorSet()
@ -420,7 +498,7 @@ void GPURaytracer2::CreateDescriptorSet()
descriptorPool = DescriptorPoolBuilder()
.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1)
.AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1)
.AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1)
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 3)
.MaxSets(1)
.DebugName("descriptorPool")
@ -431,7 +509,7 @@ void GPURaytracer2::CreateDescriptorSet()
WriteDescriptors()
.AddAccelerationStructure(descriptorSet.get(), 0, tlAccelStruct.get())
.AddBuffer(descriptorSet.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, uniformBuffer.get(), 0, sizeof(Uniforms2))
.AddBuffer(descriptorSet.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniformBuffer.get(), 0, sizeof(Uniforms2))
.AddBuffer(descriptorSet.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceIndexBuffer.get())
.AddBuffer(descriptorSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, surfaceBuffer.get())
.AddBuffer(descriptorSet.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, lightBuffer.get())

View file

@ -18,8 +18,16 @@ struct PushConstants2
{
uint32_t LightStart;
uint32_t LightEnd;
int32_t surfaceIndex;
int32_t pushPadding;
int32_t SurfaceIndex;
int32_t PushPadding1;
vec2 TileTL;
vec2 TileBR;
vec3 LightmapOrigin;
float PushPadding2;
vec3 LightmapStepX;
float PushPadding3;
vec3 LightmapStepY;
float PushPadding4;
};
struct SurfaceInfo2
@ -47,6 +55,14 @@ struct LightInfo2
float Padding2;
};
struct LightmapImage
{
std::unique_ptr<VulkanImage> Image;
std::unique_ptr<VulkanImageView> View;
std::unique_ptr<VulkanFramebuffer> Framebuffer;
std::unique_ptr<VulkanBuffer> Transfer;
};
class GPURaytracer2
{
public:
@ -62,9 +78,10 @@ private:
void CreateTopLevelAccelerationStructure();
void CreateShaders();
void CreatePipeline();
void CreateFrameBuffer();
void CreateDescriptorSet();
LightmapImage CreateImage(int width, int height);
void BeginCommands();
void FinishCommands();
@ -108,10 +125,6 @@ private:
std::unique_ptr<VulkanPipeline> pipeline;
std::unique_ptr<VulkanRenderPass> renderPass;
std::unique_ptr<VulkanImage> framebufferImage;
std::unique_ptr<VulkanImageView> framebufferImageView;
std::unique_ptr<VulkanFramebuffer> framebuffer;
std::unique_ptr<VulkanBuffer> uniformBuffer;
std::unique_ptr<VulkanBuffer> uniformTransferBuffer;

View file

@ -192,7 +192,7 @@ std::unique_ptr<VulkanShader> ShaderBuilder::Create(const char *shadername, Vulk
bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules);
if (!compileSuccess)
{
throw std::runtime_error(std::string("Shader compile failed: ") + shader.getInfoLog());
throw std::runtime_error(std::string("Could not compile shader ") + shadername + ": " + shader.getInfoLog());
}
glslang::TProgram program;
@ -200,7 +200,7 @@ std::unique_ptr<VulkanShader> ShaderBuilder::Create(const char *shadername, Vulk
bool linkSuccess = program.link(EShMsgDefault);
if (!linkSuccess)
{
throw std::runtime_error(std::string("Shader link failed: ") + program.getInfoLog());
throw std::runtime_error(std::string("Could not link shader ") + shadername + ": " + program.getInfoLog());
}
glslang::TIntermediate *intermediate = program.getIntermediate(stage);

View file

@ -200,9 +200,13 @@ void VulkanDevice::createDevice()
queueCreateInfos.push_back(queueCreateInfo);
}
VkPhysicalDeviceRayQueryFeaturesKHR rayqueryFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR };
rayqueryFeatures.rayQuery = true;
VkPhysicalDeviceRayTracingPipelineFeaturesKHR raytracingFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_FEATURES_KHR };
raytracingFeatures.rayTracingPipeline = true;
raytracingFeatures.rayTraversalPrimitiveCulling = true;
raytracingFeatures.pNext = &rayqueryFeatures;
VkPhysicalDeviceAccelerationStructureFeaturesKHR deviceAccelFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR };
deviceAccelFeatures.accelerationStructure = true;

View file

@ -74,7 +74,7 @@ public:
VkPhysicalDeviceFeatures enabledDeviceFeatures = {};
std::vector<const char *> enabledDeviceExtensions = {
//VK_KHR_SWAPCHAIN_EXTENSION_NAME,
//VK_KHR_RAY_QUERY_EXTENSION_NAME,
VK_KHR_RAY_QUERY_EXTENSION_NAME,
VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME,
VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME,
VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME

View file

@ -7,6 +7,7 @@
class VulkanCommandPool;
class VulkanDescriptorPool;
class VulkanCommandBuffer;
class VulkanSemaphore
{
@ -307,13 +308,15 @@ class RenderPassBegin
public:
RenderPassBegin();
void setRenderPass(VulkanRenderPass *renderpass);
void setRenderArea(int x, int y, int width, int height);
void setFramebuffer(VulkanFramebuffer *framebuffer);
void addClearColor(float r, float g, float b, float a);
void addClearDepth(float value);
void addClearStencil(int value);
void addClearDepthStencil(float depthValue, int stencilValue);
RenderPassBegin& RenderPass(VulkanRenderPass *renderpass);
RenderPassBegin& RenderArea(int x, int y, int width, int height);
RenderPassBegin& Framebuffer(VulkanFramebuffer *framebuffer);
RenderPassBegin& AddClearColor(float r, float g, float b, float a);
RenderPassBegin& AddClearDepth(float value);
RenderPassBegin& AddClearStencil(int value);
RenderPassBegin& AddClearDepthStencil(float depthValue, int stencilValue);
void Execute(VulkanCommandBuffer* cmdbuffer, VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE);
VkRenderPassBeginInfo renderPassInfo = {};
@ -381,7 +384,6 @@ public:
void copyQueryPoolResults(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags);
void pushConstants(VulkanPipelineLayout *layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues);
void pushConstants(VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues);
void beginRenderPass(const RenderPassBegin &renderPassBegin, VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE);
void beginRenderPass(const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents);
void nextSubpass(VkSubpassContents contents);
void endRenderPass();
@ -509,25 +511,28 @@ inline RenderPassBegin::RenderPassBegin()
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
}
inline void RenderPassBegin::setRenderPass(VulkanRenderPass *renderPass)
inline RenderPassBegin& RenderPassBegin::RenderPass(VulkanRenderPass *renderPass)
{
renderPassInfo.renderPass = renderPass->renderPass;
return *this;
}
inline void RenderPassBegin::setRenderArea(int x, int y, int width, int height)
inline RenderPassBegin& RenderPassBegin::RenderArea(int x, int y, int width, int height)
{
renderPassInfo.renderArea.offset.x = x;
renderPassInfo.renderArea.offset.y = y;
renderPassInfo.renderArea.extent.width = width;
renderPassInfo.renderArea.extent.height = height;
return *this;
}
inline void RenderPassBegin::setFramebuffer(VulkanFramebuffer *framebuffer)
inline RenderPassBegin& RenderPassBegin::Framebuffer(VulkanFramebuffer *framebuffer)
{
renderPassInfo.framebuffer = framebuffer->framebuffer;
return *this;
}
inline void RenderPassBegin::addClearColor(float r, float g, float b, float a)
inline RenderPassBegin& RenderPassBegin::AddClearColor(float r, float g, float b, float a)
{
VkClearValue clearValue = { };
clearValue.color = { r, g, b, a };
@ -535,9 +540,10 @@ inline void RenderPassBegin::addClearColor(float r, float g, float b, float a)
renderPassInfo.clearValueCount = (uint32_t)clearValues.size();
renderPassInfo.pClearValues = clearValues.data();
return *this;
}
inline void RenderPassBegin::addClearDepth(float value)
inline RenderPassBegin& RenderPassBegin::AddClearDepth(float value)
{
VkClearValue clearValue = { };
clearValue.depthStencil.depth = value;
@ -545,9 +551,10 @@ inline void RenderPassBegin::addClearDepth(float value)
renderPassInfo.clearValueCount = (uint32_t)clearValues.size();
renderPassInfo.pClearValues = clearValues.data();
return *this;
}
inline void RenderPassBegin::addClearStencil(int value)
inline RenderPassBegin& RenderPassBegin::AddClearStencil(int value)
{
VkClearValue clearValue = { };
clearValue.depthStencil.stencil = value;
@ -555,9 +562,10 @@ inline void RenderPassBegin::addClearStencil(int value)
renderPassInfo.clearValueCount = (uint32_t)clearValues.size();
renderPassInfo.pClearValues = clearValues.data();
return *this;
}
inline void RenderPassBegin::addClearDepthStencil(float depthValue, int stencilValue)
inline RenderPassBegin& RenderPassBegin::AddClearDepthStencil(float depthValue, int stencilValue)
{
VkClearValue clearValue = { };
clearValue.depthStencil.depth = depthValue;
@ -566,6 +574,12 @@ inline void RenderPassBegin::addClearDepthStencil(float depthValue, int stencilV
renderPassInfo.clearValueCount = (uint32_t)clearValues.size();
renderPassInfo.pClearValues = clearValues.data();
return *this;
}
inline void RenderPassBegin::Execute(VulkanCommandBuffer* cmdbuffer, VkSubpassContents contents)
{
cmdbuffer->beginRenderPass(&renderPassInfo, contents);
}
/////////////////////////////////////////////////////////////////////////////
@ -896,11 +910,6 @@ inline void VulkanCommandBuffer::pushConstants(VkPipelineLayout layout, VkShader
vkCmdPushConstants(buffer, layout, stageFlags, offset, size, pValues);
}
inline void VulkanCommandBuffer::beginRenderPass(const RenderPassBegin &renderPassBegin, VkSubpassContents contents)
{
beginRenderPass(&renderPassBegin.renderPassInfo, contents);
}
inline void VulkanCommandBuffer::beginRenderPass(const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents)
{
vkCmdBeginRenderPass(buffer, pRenderPassBegin, contents);