{ limits = { //FIXME this really needs to be an external variable as the C code //needs to agree on the size, so it might as well set maxSamplers //directly (and any other such variable) maxSamplers = "min (256u, $physDevLimits.maxPerStageDescriptorSamplers)"; }; samplers = { quakepic = { magFilter = nearest; minFilter = nearest; mipmapMode = nearest; addressModeU = clamp_to_edge; addressModeV = clamp_to_edge; addressModeW = clamp_to_edge; mipLodBias = 0; anisotropyEnable = false; maxAnisotropy = 0; compareEnable = false; compareOp = always; minLod = 0; maxLod = 0; borderColor = float_transparent_black; unnormalizedCoordinates = false; }; quakebsp_sampler = { magFilter = linear; minFilter = linear; mipmapMode = linear; addressModeU = repeat; addressModeV = repeat; addressModeW = repeat; mipLodBias = 0; anisotropyEnable = false; maxAnisotropy = 0; compareEnable = false; compareOp = always; minLod = 0; maxLod = 4; borderColor = float_transparent_black; unnormalizedCoordinates = false; }; alias_sampler = { magFilter = linear; minFilter = linear; mipmapMode = linear; addressModeU = clamp_to_edge; addressModeV = clamp_to_edge; addressModeW = clamp_to_edge; mipLodBias = 0; anisotropyEnable = false; maxAnisotropy = 0; compareEnable = false; compareOp = always; minLod = 0; maxLod = 1000; borderColor = float_transparent_black; unnormalizedCoordinates = false; }; sprite_sampler = $properties.samplers.alias_sampler; shadow_sampler = { magFilter = linear; minFilter = linear; mipmapMode = linear; addressModeU = clamp_to_edge; addressModeV = clamp_to_edge; addressModeW = clamp_to_edge; mipLodBias = 0; anisotropyEnable = false; maxAnisotropy = 0; compareEnable = true; compareOp = greater_or_equal; minLod = 0; maxLod = 1000; borderColor = float_transparent_black; unnormalizedCoordinates = false; }; }; descriptorPools = { matrix_pool = { flags = 0; maxSets = $frames.size; bindings = ( { type = uniform_buffer; descriptorCount = $frames.size; }, ); }; twod_pool = { flags = 0; maxSets = $frames.size; bindings = ( { type = combined_image_sampler; descriptorCount = $frames.size; }, ); }; bone_pool = { flags = free_descriptor_set; maxSets = 512; bindings = ( { type = storage_buffer; descriptorCount = $properties.descriptorPools.bone_pool.maxSets; }, ); }; texture_pool = { flags = free_descriptor_set; maxSets = 512; bindings = ( { type = combined_image_sampler; descriptorCount = $properties.descriptorPools.texture_pool.maxSets; }, ); }; particle_pool = { flags = 0; maxSets = $frames.size; bindings = ( { type = storage_buffer; descriptorCount = 3; }, ); }; sprite_pool = { flags = free_descriptor_set; maxSets = 64; //FIXME cvar? bindings = ( { type = uniform_buffer; descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; }, { type = combined_image_sampler; descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; }, ); }; //FIXME probably should just share a larger pool alias_pool = $properties.descriptorPools.texture_pool; quakebsp_pool = $properties.descriptorPools.texture_pool; lighting_attach_pool = { flags = 0; maxSets = $frames.size; bindings = ( { type = input_attachment; descriptorCount = "5z * $frames.size"; }, ); }; lighting_lights_pool = { flags = 0; maxSets = $frames.size; bindings = ( { type = uniform_buffer; descriptorCount = $frames.size; }, ); }; lighting_shadow_pool = { flags = 0; maxSets = $frames.size; bindings = ( { type = combined_image_sampler; descriptorCount = "$frames.size * size_t($properties.limits.maxSamplers)"; }, ); }; compose_attach_pool = { flags = 0; maxSets = $frames.size; bindings = ( { type = input_attachment; descriptorCount = "2z * $frames.size"; }, ); }; }; setLayouts = { matrix_set = { bindings = ( { binding = 0; descriptorType = uniform_buffer; descriptorCount = 1; stageFlags = vertex|geometry; }, ); }; twod_set = { bindings = ( { binding = 0; descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; }, ); }; texture_set = { bindings = ( { binding = 0; descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; }, ); }; bone_set = { bindings = ( { binding = 0; descriptorType = storage_buffer; descriptorCount = 1; stageFlags = vertex; }, ); }; sprite_set = { bindings = ( { binding = 0; descriptorType = uniform_buffer; descriptorCount = 1; stageFlags = vertex; }, { binding = 1; descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; }, ); }; lighting_attach = { bindings = ( { binding = 0; descriptorType = input_attachment; descriptorCount = 1; stageFlags = fragment; }, { binding = 1; descriptorType = input_attachment; descriptorCount = 1; stageFlags = fragment; }, { binding = 2; descriptorType = input_attachment; descriptorCount = 1; stageFlags = fragment; }, { binding = 3; descriptorType = input_attachment; descriptorCount = 1; stageFlags = fragment; }, { binding = 4; descriptorType = input_attachment; descriptorCount = 1; stageFlags = fragment; }, ); }; lighting_lights = { bindings = ( { binding = 0; descriptorType = uniform_buffer; descriptorCount = 1; stageFlags = fragment; }, ); }; lighting_shadow = { bindings = ( { binding = 0; descriptorType = combined_image_sampler; descriptorCount = $properties.limits.maxSamplers; stageFlags = fragment; }, ); }; compose_attach = { bindings = ( { binding = 0; descriptorType = input_attachment; descriptorCount = 1; stageFlags = fragment; }, { binding = 1; descriptorType = input_attachment; descriptorCount = 1; stageFlags = fragment; }, ); }; particle_set = { bindings = ( { binding = 0; descriptorType = storage_buffer; descriptorCount = 1; stageFlags = compute; }, { binding = 1; descriptorType = storage_buffer; descriptorCount = 1; stageFlags = compute; }, { binding = 2; descriptorType = storage_buffer; descriptorCount = 1; stageFlags = compute; }, ); }; }; pipelineLayouts = { twod_layout = { setLayouts = (matrix_set, twod_set); }; quakebsp_layout = { setLayouts = (matrix_set, texture_set, texture_set); pushConstantRanges = ( { stageFlags = vertex; offset = 0; size = "16 * 4"; }, { stageFlags = fragment; offset = 64; size = "4 * 4 + 4"; }, ); }; alias_layout = { setLayouts = (matrix_set, texture_set); pushConstantRanges = ( { stageFlags = vertex; offset = 0; size = "16 * 4 + 4"; }, { stageFlags = fragment; offset = 68; size = "3 * 4 + 2 * 4 * 4 + 4"; }, ); }; iqm_layout = { setLayouts = (matrix_set, texture_set, bone_set); pushConstantRanges = ( { stageFlags = vertex; offset = 0; size = "16 * 4 + 4"; }, { stageFlags = fragment; offset = 68; size = "3 * 4 + 2 * 4 * 4 + 4"; }, ); }; sprite_layout = { setLayouts = (matrix_set, sprite_set); pushConstantRanges = ( { stageFlags = vertex; offset = 0; size = "16 * 4 + 4"; }, { stageFlags = fragment; offset = 64; size = "2 * 4 + 2 * 4 + 4 * 4"; }, ); }; lighting_layout = { setLayouts = (lighting_attach, lighting_lights, lighting_shadow); }; compose_layout = { setLayouts = (compose_attach); }; partphysics_layout = { setLayouts = (particle_set); pushConstantRanges = ( { stageFlags = compute; offset = 0; size = "16 * 4 + 4"; }, ); }; partupdate_layout = { setLayouts = (particle_set, particle_set, particle_set); }; partdraw_layout = { setLayouts = (matrix_set); pushConstantRanges = ( { stageFlags = vertex; offset = 0; size = "16 * 4"; }, ); }; }; depthStencil = { test_and_write = { depthTestEnable = true; depthWriteEnable = true; depthCompareOp = less_or_equal; depthBoundsTestEnable = false; stencilTestEnable = false; }; test_only = { depthTestEnable = true; depthWriteEnable = false; depthCompareOp = less_or_equal; depthBoundsTestEnable = false; stencilTestEnable = false; }; disable = { depthTestEnable = false; depthWriteEnable = false; depthCompareOp = less_or_equal; depthBoundsTestEnable = false; stencilTestEnable = false; }; }; inputAssembly = { alias = { topology = triangle_list; primitiveRestartEnable = false; }; brush = { topology = triangle_fan; primitiveRestartEnable = true; }; iqm = { topology = triangle_list; primitiveRestartEnable = false; }; twod = { topology = triangle_strip; primitiveRestartEnable = true; }; sprite = { topology = triangle_strip; primitiveRestartEnable = true; }; }; vertexInput = { index_only = { bindings = (); attributes = (); }; alias = { bindings = ( { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, { binding = 1; stride = "2 * 4 * 4"; inputRate = vertex; }, { binding = 2; stride = "2 * 4"; inputRate = vertex; }, ); attributes = ( { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, { location = 2; binding = 1; format = r32g32b32a32_sfloat; offset = 0; }, { location = 3; binding = 1; format = r32g32b32a32_sfloat; offset = 16; }, { location = 4; binding = 2; format = r32g32_sfloat; offset = 0; }, ); }; brush = { bindings = ( { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, ); attributes = ( { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, ); }; iqm = { bindings = ( { binding = 0; stride = 20; inputRate = vertex; }, { binding = 1; stride = 40; inputRate = vertex; }, ); attributes = ( { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 12; }, // bonindices { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 16; }, // boneweights { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color ); }; particle = { bindings = ( { binding = 0; stride = "4 * 4 * 4"; inputRate = vertex; }, ); attributes = ( { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, ); }; twod = { bindings = ( { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, ); attributes = ( { location = 0; binding = 0; format = r32g32_sfloat; offset = 0; }, { location = 1; binding = 0; format = r32g32_sfloat; offset = 8; }, { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, ); }; }; rasterization = { cw_cull_back = { depthClampEnable = false; rasterizerDiscardEnable = false; polygonMode = fill; cullMode = back; frontFace = clockwise; depthBiasEnable = false; lineWidth = 1; }; counter_cw_cull_back = { depthClampEnable = false; rasterizerDiscardEnable = false; polygonMode = fill; cullMode = back; frontFace = counter_clockwise; depthBiasEnable = false; lineWidth = 1; }; }; multisample = { rasterizationSamples = $msaaSamples; sampleShadingEnable = false; minSampleShading = 0.5f; alphaToCoverageEnable = false; alphaToOneEnable = false; }; viewport = { viewports = ( { x = 0; y = 0; width = 640; height = 480; minDepth = 0; maxDepth = 1; } ); scissors = ( { offset = { x = 0; y = 0 }; extent = { width = 640; height = 480; }; }, ); }; attachmentBlendOp = { disabled = { blendEnable = false; srcColorBlendFactor = src_alpha; dstColorBlendFactor = one_minus_src_alpha; colorBlendOp = add; srcAlphaBlendFactor = src_alpha; dstAlphaBlendFactor = one_minus_src_alpha; alphaBlendOp = add; colorWriteMask = r|g|b|a; }; alpha_blend = { blendEnable = true; srcColorBlendFactor = src_alpha; dstColorBlendFactor = one_minus_src_alpha; colorBlendOp = add; srcAlphaBlendFactor = src_alpha; dstAlphaBlendFactor = one_minus_src_alpha; alphaBlendOp = add; colorWriteMask = r|g|b|a; }; }; fstriangle = { vertexStage = { stage = vertex; name = main; module = $builtin/fstriangle.vert; }; vertexInput = { bindings = (); attributes = (); }; inputAssembly = { topology = triangle_list; primitiveRestartEnable = false; }; colorBlend = { logicOpEnable = false; attachments = ($properties.attachmentBlendOp.disabled); }; }; pipelines = { base = { viewport = $properties.viewport; rasterization = $properties.rasterization.counter_cw_cull_back; multisample = $properties.multisample; depthStencil = $properties.depthStencil.disable; colorBlend = { logicOpEnable = false; attachments = ( $properties.attachmentBlendOp.disabled, $properties.attachmentBlendOp.disabled, $properties.attachmentBlendOp.disabled, $properties.attachmentBlendOp.disabled, ); }; dynamic = { dynamicState = ( viewport, scissor ); }; renderPass = renderpass; }; depth_base = { @inherit = $properties.pipelines.base; subpass = 0; rasterization = $properties.rasterization.cw_cull_back; depthStencil = $properties.depthStencil.test_and_write; }; trans_base = { @inherit = $properties.pipelines.base; subpass = 1; rasterization = $properties.rasterization.cw_cull_back; depthStencil = $properties.depthStencil.test_only; colorBlend = { logicOpEnable = false; attachments = ($properties.attachmentBlendOp.disabled); }; }; gbuf_base = { @inherit = $properties.pipelines.base; subpass = 2; rasterization = $properties.rasterization.cw_cull_back; depthStencil = $properties.depthStencil.test_only; dynamic = {//FIXME why? dynamicState = ( viewport, scissor ); }; }; comp_base = { @inherit = $properties.pipelines.base; vertexInput = $properties.fstriangle.vertexInput; inputAssembly = $properties.fstriangle.inputAssembly; colorBlend = $properties.fstriangle.colorBlend; }; shadow_base = { @inherit = $properties.pipelines.depth_base; }; alias_shadow = { @inherit = $properties.pipelines.shadow_base; stages = ( { stage = vertex; name = main; module = $builtin/alias_shadow.vert; }, ); vertexInput = { bindings = ( "$properties.vertexInput.alias.bindings[0]", "$properties.vertexInput.alias.bindings[1]", ); attributes = ( "$properties.vertexInput.alias.attributes[0]", "$properties.vertexInput.alias.attributes[1]", "$properties.vertexInput.alias.attributes[2]", "$properties.vertexInput.alias.attributes[3]", ); }; inputAssembly = $properties.inputAssembly.alias; layout = alias_layout; }; bsp_shadow = { @inherit = $properties.pipelines.shadow_base; stages = ( { stage = vertex; name = main; module = $builtin/bsp_shadow.vert; }, ); vertexInput = { bindings = ( "$properties.vertexInput.brush.bindings[0]", ); attributes = ( "$properties.vertexInput.brush.attributes[0]", ); }; inputAssembly = $properties.inputAssembly.brush; }; alias_depth = { @inherit = $properties.pipelines.depth_base; stages = ( { stage = vertex; name = main; module = $builtin/alias_depth.vert; }, ); vertexInput = { // depth pass doesn't use UVs bindings = ( "$properties.vertexInput.alias.bindings[0]", "$properties.vertexInput.alias.bindings[1]", ); attributes = ( "$properties.vertexInput.alias.attributes[0]", "$properties.vertexInput.alias.attributes[1]", "$properties.vertexInput.alias.attributes[2]", "$properties.vertexInput.alias.attributes[3]", ); }; inputAssembly = $properties.inputAssembly.alias; layout = alias_layout; }; alias_gbuf = { @inherit = $properties.pipelines.gbuf_base; stages = ( { stage = vertex; name = main; module = $builtin/alias.vert; }, { stage = fragment; name = main; module = $builtin/alias_gbuf.frag; }, ); vertexInput = $properties.vertexInput.alias; inputAssembly = $properties.inputAssembly.alias; layout = alias_layout; }; bsp_depth = { @inherit = $properties.pipelines.depth_base; stages = ( { stage = vertex; name = main; module = $builtin/bsp_depth.vert; }, ); vertexInput = { bindings = ( "$properties.vertexInput.brush.bindings[0]", ); attributes = ( "$properties.vertexInput.brush.attributes[0]", ); }; inputAssembly = $properties.inputAssembly.brush; layout = quakebsp_layout; }; bsp_gbuf = { @inherit = $properties.pipelines.gbuf_base; stages = ( { stage = vertex; name = main; module = $builtin/bsp_gbuf.vert; }, { stage = geometry; name = main; module = $builtin/bsp_gbuf.geom; }, { stage = fragment; name = main; module = $builtin/bsp_gbuf.frag; }, ); vertexInput = $properties.vertexInput.brush; inputAssembly = $properties.inputAssembly.brush; layout = quakebsp_layout; }; bsp_skybox = { @inherit = $properties.pipelines.trans_base; stages = ( { stage = vertex; name = main; module = $builtin/quakebsp.vert; }, { stage = fragment; name = main; module = $builtin/bsp_sky.frag; specializationInfo = { mapEntries = ( // doSkyBox { size = 4; offset = 0; constantID = 0; }, // doSkySheet { size = 4; offset = 4; constantID = 1; }, ); data = "array(1, 0)"; }; }, ); vertexInput = $properties.vertexInput.brush; inputAssembly = $properties.inputAssembly.brush; layout = quakebsp_layout; }; bsp_skysheet = { @inherit = $properties.pipelines.trans_base; stages = ( { stage = vertex; name = main; module = $builtin/quakebsp.vert; }, { stage = fragment; name = main; module = $builtin/bsp_sky.frag; specializationInfo = { mapEntries = ( // doSkyBox { size = 4; offset = 0; constantID = 0; }, // doSkySheet { size = 4; offset = 4; constantID = 1; }, ); data = "array(0, 1)"; }; }, ); vertexInput = $properties.vertexInput.brush; inputAssembly = $properties.inputAssembly.brush; layout = quakebsp_layout; }; bsp_turb = { @inherit = $properties.pipelines.trans_base; stages = ( { stage = vertex; name = main; module = $builtin/quakebsp.vert; }, { stage = fragment; name = main; module = $builtin/bsp_turb.frag; }, ); vertexInput = $properties.vertexInput.brush; inputAssembly = $properties.inputAssembly.brush; layout = quakebsp_layout; }; iqm_depth = { @inherit = $properties.pipelines.depth_base; stages = ( { stage = vertex; name = main; module = $builtin/iqm.vert; specializationInfo = { mapEntries = ( // IQMDepthOnly { size = 4; offset = 0; constantID = 0; }, ); data = "array(1)"; }; }, ); vertexInput = $properties.vertexInput.iqm; /*vertexInput = { bindings = ( "$properties.vertexInput.iqm.bindings[0]", ); attributes = ( "$properties.vertexInput.iqm.attributes[0]", "$properties.vertexInput.iqm.attributes[1]", "$properties.vertexInput.iqm.attributes[2]", ); };*/ inputAssembly = $properties.inputAssembly.iqm; layout = iqm_layout; }; iqm_gbuf = { @inherit = $properties.pipelines.gbuf_base; stages = ( { stage = vertex; name = main; module = $builtin/iqm.vert; specializationInfo = { mapEntries = ( // !IQMDepthOnly { size = 4; offset = 0; constantID = 0; }, ); data = "array(0)"; }; }, { stage = fragment; name = main; module = $builtin/iqm.frag; }, ); vertexInput = $properties.vertexInput.iqm; inputAssembly = $properties.inputAssembly.iqm; layout = iqm_layout; }; partdraw = { @inherit = $properties.pipelines.trans_base; stages = ( { stage = vertex; name = main; module = $builtin/particle.vert; }, { stage = geometry; name = main; module = $builtin/particle.geom; }, { stage = fragment; name = main; module = $builtin/particle.frag; }, ); vertexInput = $properties.vertexInput.particle; inputAssembly = $properties.inputAssembly.sprite; layout = partdraw_layout; }; sprite_gbuf = { @inherit = $properties.pipelines.gbuf_base; stages = ( { stage = vertex; name = main; module = $builtin/sprite_gbuf.vert; }, { stage = fragment; name = main; module = $builtin/sprite_gbuf.frag; }, ); vertexInput = $properties.vertexInput.index_only; inputAssembly = $properties.inputAssembly.sprite; layout = sprite_layout; }; sprite_depth = { @inherit = $properties.pipelines.depth_base; stages = ( { stage = vertex; name = main; module = $builtin/sprite_depth.vert; }, { stage = fragment; name = main; module = $builtin/sprite_depth.frag; }, ); vertexInput = $properties.vertexInput.index_only; inputAssembly = $properties.inputAssembly.alias; layout = sprite_layout; }; twod = { @inherit = $properties.pipelines.trans_base;//FIXME should be sparate stages = ( { stage = vertex; name = main; module = $builtin/twod.vert; }, { stage = fragment; name = main; module = $builtin/twod.frag; }, ); vertexInput = $properties.vertexInput.twod; inputAssembly = $properties.inputAssembly.twod; rasterization = $properties.rasterization.counter_cw_cull_back; colorBlend = { logicOpEnable = false; attachments = ($properties.attachmentBlendOp.alpha_blend); }; layout = twod_layout; }; lighting = { @inherit = $properties.pipelines.comp_base; subpass = 3; stages = ( $properties.fstriangle.vertexStage, { stage = fragment; name = main; module = $builtin/lighting.frag; specializationInfo = { mapEntries = ( { size = 4; offset = 0; constantID = 0; }, ); data = "array(uint($properties.limits.maxSamplers))"; }; }, ); layout = lighting_layout; }; compose = { @inherit = $properties.pipelines.comp_base; subpass = 4; stages = ( $properties.fstriangle.vertexStage, { stage = fragment; name = main; module = $builtin/compose.frag; }, ); layout = compose_layout; }; partphysics = { stage = { stage = compute; name = main; module = $builtin/partphysics.comp; }; layout = partphysics_layout; }; partupdate = { stage = { stage = compute; name = main; module = $builtin/partupdate.comp; }; layout = partupdate_layout; }; }; }