mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-13 19:29:14 +01:00
[dxvk] Implemented shader resource binding
This commit is contained in:
parent
a6bf7659b0
commit
b5d068366d
@ -33,6 +33,26 @@ namespace dxvk {
|
||||
m_acquireSync = m_device->createSemaphore();
|
||||
m_presentSync = m_device->createSemaphore();
|
||||
|
||||
// Sampler for presentation
|
||||
DxvkSamplerCreateInfo samplerInfo;
|
||||
samplerInfo.magFilter = VK_FILTER_NEAREST;
|
||||
samplerInfo.minFilter = VK_FILTER_NEAREST;
|
||||
samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
samplerInfo.mipmapLodBias = 0.0f;
|
||||
samplerInfo.mipmapLodMin = 0.0f;
|
||||
samplerInfo.mipmapLodMax = 0.0f;
|
||||
samplerInfo.useAnisotropy = VK_FALSE;
|
||||
samplerInfo.maxAnisotropy = 1.0f;
|
||||
samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
|
||||
samplerInfo.compareToDepth = VK_FALSE;
|
||||
samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
samplerInfo.usePixelCoord = VK_FALSE;
|
||||
|
||||
m_sampler = m_device->createSampler(samplerInfo);
|
||||
|
||||
// Set up context state. The shader bindings and the
|
||||
// constant state objects will never be modified.
|
||||
m_context->bindGraphicsPipeline(createPipeline());
|
||||
@ -133,9 +153,12 @@ namespace dxvk {
|
||||
|
||||
m_context->setViewports(1, &viewport, &scissor);
|
||||
|
||||
// TODO bind back buffer as a shader resource
|
||||
// m_context->bindSampler(0, m_sampler);
|
||||
// m_context->bindSampledImage(1, view);
|
||||
m_context->bindResourceSampler(
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
BindingIds::Sampler, m_sampler);
|
||||
m_context->bindResourceImage(
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
BindingIds::Texture, view);
|
||||
m_context->draw(4, 1, 0, 0);
|
||||
|
||||
m_device->submitCommandList(
|
||||
@ -279,10 +302,26 @@ namespace dxvk {
|
||||
uint32_t typeVec2 = module.defVectorType(typeF32, 2);
|
||||
uint32_t typeVec4 = module.defVectorType(typeF32, 4);
|
||||
uint32_t typeFn = module.defFunctionType(typeVoid, 0, nullptr);
|
||||
uint32_t typeSampler = module.defSamplerType();
|
||||
uint32_t typeTexture = module.defImageType(
|
||||
typeF32, spv::Dim2D, 0, 0, 0, 1, spv::ImageFormatUnknown);
|
||||
uint32_t typeSampledTex = module.defSampledImageType(typeTexture);
|
||||
|
||||
// Pointer type definitions
|
||||
uint32_t ptrInputVec2 = module.defPointerType(typeVec2, spv::StorageClassInput);
|
||||
uint32_t ptrOutputVec4 = module.defPointerType(typeVec4, spv::StorageClassOutput);
|
||||
uint32_t ptrSampler = module.defPointerType(typeSampler, spv::StorageClassUniformConstant);
|
||||
uint32_t ptrTexture = module.defPointerType(typeTexture, spv::StorageClassUniformConstant);
|
||||
|
||||
// Sampler
|
||||
uint32_t rcSampler = module.newVar(ptrSampler, spv::StorageClassUniformConstant);
|
||||
module.decorateDescriptorSet(rcSampler, 0);
|
||||
module.decorateBinding(rcSampler, BindingIds::Sampler);
|
||||
|
||||
// Texture
|
||||
uint32_t rcTexture = module.newVar(ptrTexture, spv::StorageClassUniformConstant);
|
||||
module.decorateDescriptorSet(rcTexture, 0);
|
||||
module.decorateBinding(rcTexture, BindingIds::Texture);
|
||||
|
||||
// Input variable: Texture coordinates
|
||||
uint32_t inTexCoord = module.newVar(
|
||||
@ -299,13 +338,14 @@ namespace dxvk {
|
||||
module.opLabel(module.allocateId());
|
||||
|
||||
// Load texture coordinates
|
||||
uint32_t tmpTexCoord = module.opLoad(typeVec2, inTexCoord);
|
||||
|
||||
// Compute final color
|
||||
uint32_t swizzleIndices[4] = { 0, 1, 2, 3 };
|
||||
uint32_t tmpColor = module.opVectorShuffle(
|
||||
typeVec4, tmpTexCoord, tmpTexCoord, 4, swizzleIndices);
|
||||
module.opStore(outColor, tmpColor);
|
||||
module.opStore(outColor,
|
||||
module.opImageSampleImplicitLod(
|
||||
typeVec4,
|
||||
module.opSampledImage(
|
||||
typeSampledTex,
|
||||
module.opLoad(typeTexture, rcTexture),
|
||||
module.opLoad(typeSampler, rcSampler)),
|
||||
module.opLoad(typeVec2, inTexCoord)));
|
||||
|
||||
module.opReturn();
|
||||
module.functionEnd();
|
||||
@ -325,12 +365,14 @@ namespace dxvk {
|
||||
|
||||
|
||||
Rc<DxvkBindingLayout> DxgiPresenter::createBindingLayout() {
|
||||
std::array<DxvkBindingInfo, 2> bindings;
|
||||
bindings.at(0).type = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
bindings.at(0).stages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
std::array<DxvkDescriptorSlot, 2> bindings;
|
||||
bindings.at(BindingIds::Sampler).slot = BindingIds::Sampler;
|
||||
bindings.at(BindingIds::Sampler).type = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
bindings.at(BindingIds::Sampler).stages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
bindings.at(1).type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
bindings.at(1).stages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
bindings.at(BindingIds::Texture).slot = BindingIds::Texture;
|
||||
bindings.at(BindingIds::Texture).type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
bindings.at(BindingIds::Texture).stages = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
|
||||
return m_device->createBindingLayout(
|
||||
bindings.size(), bindings.data());
|
||||
|
@ -43,6 +43,11 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
enum BindingIds : uint32_t {
|
||||
Sampler = 0,
|
||||
Texture = 1,
|
||||
};
|
||||
|
||||
Rc<DxvkDevice> m_device;
|
||||
Rc<DxvkContext> m_context;
|
||||
|
||||
@ -52,6 +57,8 @@ namespace dxvk {
|
||||
Rc<DxvkSemaphore> m_acquireSync;
|
||||
Rc<DxvkSemaphore> m_presentSync;
|
||||
|
||||
Rc<DxvkSampler> m_sampler;
|
||||
|
||||
Rc<DxvkShader> createVertexShader();
|
||||
Rc<DxvkShader> createFragmentShader();
|
||||
|
||||
|
@ -45,9 +45,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
// Set initial window mode and fullscreen state
|
||||
if (FAILED(this->ResizeTarget(&pDesc->BufferDesc)))
|
||||
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to set initial display mode");
|
||||
|
||||
if (FAILED(this->SetFullscreenState(!pDesc->Windowed, nullptr)))
|
||||
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to set initial fullscreen state");
|
||||
|
||||
@ -319,7 +316,7 @@ namespace dxvk {
|
||||
|
||||
DxvkImageCreateInfo imageInfo;
|
||||
imageInfo.type = VK_IMAGE_TYPE_2D;
|
||||
imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||
imageInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||
imageInfo.sampleCount = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageInfo.extent.width = m_desc.BufferDesc.Width;
|
||||
imageInfo.extent.height = m_desc.BufferDesc.Height;
|
||||
|
61
src/dxvk/dxvk_binding.h
Normal file
61
src/dxvk/dxvk_binding.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_buffer.h"
|
||||
#include "dxvk_descriptor.h"
|
||||
#include "dxvk_image.h"
|
||||
#include "dxvk_sampler.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Bound shader resource
|
||||
*/
|
||||
struct DxvkShaderResourceSlot {
|
||||
Rc<DxvkSampler> sampler;
|
||||
Rc<DxvkImageView> imageView;
|
||||
Rc<DxvkBufferView> bufferView;
|
||||
DxvkBufferBinding bufferSlice;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Shader resource slots
|
||||
*/
|
||||
class DxvkShaderResourceSlots {
|
||||
|
||||
public:
|
||||
|
||||
DxvkShaderResourceSlots() { }
|
||||
DxvkShaderResourceSlots(size_t n) {
|
||||
m_resources .resize(n);
|
||||
m_descriptors.resize(n);
|
||||
}
|
||||
|
||||
uint32_t descriptorCount() const {
|
||||
return m_descriptors.size();
|
||||
}
|
||||
|
||||
const DxvkDescriptorInfo* descriptors() const {
|
||||
return m_descriptors.data();
|
||||
}
|
||||
|
||||
const DxvkShaderResourceSlot& getShaderResource(uint32_t slot) const {
|
||||
return m_resources.at(slot);
|
||||
}
|
||||
|
||||
void bindShaderResource(
|
||||
uint32_t slot,
|
||||
const DxvkShaderResourceSlot& resource,
|
||||
const DxvkDescriptorInfo& descriptor) {
|
||||
m_resources .at(slot) = resource;
|
||||
m_descriptors .at(slot) = descriptor;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector<DxvkShaderResourceSlot> m_resources;
|
||||
std::vector<DxvkDescriptorInfo> m_descriptors;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -60,7 +60,8 @@ namespace dxvk {
|
||||
|
||||
|
||||
DxvkBufferView::~DxvkBufferView() {
|
||||
|
||||
m_vkd->vkDestroyBufferView(
|
||||
m_vkd->device(), m_view, nullptr);
|
||||
}
|
||||
|
||||
}
|
@ -12,7 +12,6 @@ namespace dxvk {
|
||||
* passed to \ref DxvkDevice::createBuffer
|
||||
*/
|
||||
struct DxvkBufferCreateInfo {
|
||||
|
||||
/// Size of the buffer, in bytes
|
||||
VkDeviceSize size;
|
||||
|
||||
@ -25,7 +24,6 @@ namespace dxvk {
|
||||
|
||||
/// Allowed access patterns
|
||||
VkAccessFlags access;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -36,7 +34,6 @@ namespace dxvk {
|
||||
* are to \ref DxvkDevice::createBufferView
|
||||
*/
|
||||
struct DxvkBufferViewCreateInfo {
|
||||
|
||||
/// Buffer data format, like image data
|
||||
VkFormat format;
|
||||
|
||||
|
@ -91,6 +91,51 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandList::bindResourceDescriptors(
|
||||
VkPipelineBindPoint pipeline,
|
||||
VkPipelineLayout pipelineLayout,
|
||||
VkDescriptorSetLayout descriptorLayout,
|
||||
uint32_t descriptorCount,
|
||||
const DxvkDescriptorSlot* descriptorSlots,
|
||||
const DxvkDescriptorInfo* descriptorInfos) {
|
||||
|
||||
// Allocate a new descriptor set
|
||||
VkDescriptorSet dset = m_descAlloc.alloc(descriptorLayout);
|
||||
|
||||
// Write data to the descriptor set
|
||||
// TODO recycle vector as a class member
|
||||
std::vector<VkWriteDescriptorSet> descriptorWrites;
|
||||
descriptorWrites.resize(descriptorCount);
|
||||
|
||||
for (uint32_t i = 0; i < descriptorCount; i++) {
|
||||
auto& curr = descriptorWrites.at(i);
|
||||
auto& binding = descriptorSlots[i];
|
||||
|
||||
curr.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
curr.pNext = nullptr;
|
||||
curr.dstSet = dset;
|
||||
curr.dstBinding = i;
|
||||
curr.dstArrayElement = 0;
|
||||
curr.descriptorCount = 1;
|
||||
curr.descriptorType = binding.type;
|
||||
curr.pImageInfo = &descriptorInfos[binding.slot].image;
|
||||
curr.pBufferInfo = &descriptorInfos[binding.slot].buffer;
|
||||
curr.pTexelBufferView = &descriptorInfos[binding.slot].texelBuffer;
|
||||
}
|
||||
|
||||
m_vkd->vkUpdateDescriptorSets(
|
||||
m_vkd->device(),
|
||||
descriptorWrites.size(),
|
||||
descriptorWrites.data(),
|
||||
0, nullptr);
|
||||
|
||||
// Bind descriptor set to the pipeline
|
||||
m_vkd->vkCmdBindDescriptorSets(m_buffer,
|
||||
pipeline, pipelineLayout, 0, 1,
|
||||
&dset, 0, nullptr);
|
||||
}
|
||||
|
||||
|
||||
void DxvkCommandList::cmdBeginRenderPass(
|
||||
const VkRenderPassBeginInfo* pRenderPassBegin,
|
||||
VkSubpassContents contents) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "dxvk_descriptor.h"
|
||||
#include "dxvk_lifetime.h"
|
||||
#include "dxvk_pipeline.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
@ -76,6 +77,14 @@ namespace dxvk {
|
||||
*/
|
||||
void reset();
|
||||
|
||||
void bindResourceDescriptors(
|
||||
VkPipelineBindPoint pipeline,
|
||||
VkPipelineLayout pipelineLayout,
|
||||
VkDescriptorSetLayout descriptorLayout,
|
||||
uint32_t descriptorCount,
|
||||
const DxvkDescriptorSlot* descriptorSlots,
|
||||
const DxvkDescriptorInfo* descriptorInfos);
|
||||
|
||||
void cmdBeginRenderPass(
|
||||
const VkRenderPassBeginInfo* pRenderPassBegin,
|
||||
VkSubpassContents contents);
|
||||
|
@ -14,7 +14,7 @@ namespace dxvk {
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.stage = cs->stageInfo();
|
||||
info.layout = this->pipelineLayout();
|
||||
info.layout = m_layout->pipelineLayout();
|
||||
info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
info.basePipelineIndex = 0;
|
||||
|
||||
|
@ -25,25 +25,15 @@ namespace dxvk {
|
||||
~DxvkComputePipeline();
|
||||
|
||||
/**
|
||||
* \brief Descriptor set layout
|
||||
* \brief Pipeline layout
|
||||
*
|
||||
* The descriptor set layout for this pipeline.
|
||||
* Use this to allocate new descriptor sets.
|
||||
* \returns The descriptor set layout
|
||||
* Stores the pipeline layout and the descriptor set
|
||||
* layout, as well as information on the resource
|
||||
* slots used by the pipeline.
|
||||
* \returns Pipeline layout
|
||||
*/
|
||||
VkDescriptorSetLayout descriptorSetLayout() const {
|
||||
return m_layout->descriptorSetLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Pipeline layout layout
|
||||
*
|
||||
* The pipeline layout for this pipeline.
|
||||
* Use this to bind descriptor sets.
|
||||
* \returns The descriptor set layout
|
||||
*/
|
||||
VkPipelineLayout pipelineLayout() const {
|
||||
return m_layout->pipelineLayout();
|
||||
Rc<DxvkBindingLayout> layout() const {
|
||||
return m_layout;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,6 +53,32 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindComputePipeline(
|
||||
const Rc<DxvkComputePipeline>& pipeline) {
|
||||
if (m_state.cPipe != pipeline) {
|
||||
m_state.cPipe = pipeline;
|
||||
|
||||
m_flags.set(
|
||||
DxvkContextFlag::CpDirtyPipeline,
|
||||
DxvkContextFlag::CpDirtyResources);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindGraphicsPipeline(
|
||||
const Rc<DxvkGraphicsPipeline>& pipeline) {
|
||||
if (m_state.gPipe != pipeline) {
|
||||
m_state.gPipe = pipeline;
|
||||
|
||||
m_flags.set(
|
||||
DxvkContextFlag::GpDirtyPipeline,
|
||||
DxvkContextFlag::GpDirtyResources,
|
||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
||||
DxvkContextFlag::GpDirtyIndexBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindIndexBuffer(
|
||||
const DxvkBufferBinding& buffer) {
|
||||
if (m_state.vi.indexBuffer != buffer) {
|
||||
@ -62,25 +88,93 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindComputePipeline(
|
||||
const Rc<DxvkComputePipeline>& pipeline) {
|
||||
m_state.cp = pipeline;
|
||||
void DxvkContext::bindResourceBuffer(
|
||||
VkPipelineBindPoint pipe,
|
||||
uint32_t slot,
|
||||
const DxvkBufferBinding& buffer) {
|
||||
auto rc = this->getShaderResourceSlots(pipe);
|
||||
|
||||
m_flags.set(
|
||||
DxvkContextFlag::CpDirtyPipeline,
|
||||
DxvkContextFlag::CpDirtyResources);
|
||||
if (rc->getShaderResource(slot).bufferSlice != buffer) {
|
||||
m_flags.set(this->getResourceDirtyFlag(pipe));
|
||||
|
||||
DxvkShaderResourceSlot resource;
|
||||
resource.bufferSlice = buffer;
|
||||
|
||||
DxvkDescriptorInfo descriptor;
|
||||
|
||||
if (buffer.bufferHandle() != VK_NULL_HANDLE)
|
||||
descriptor.buffer = buffer.descriptorInfo();
|
||||
|
||||
rc->bindShaderResource(slot, resource, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindGraphicsPipeline(
|
||||
const Rc<DxvkGraphicsPipeline>& pipeline) {
|
||||
m_state.gp = pipeline;
|
||||
void DxvkContext::bindResourceTexelBuffer(
|
||||
VkPipelineBindPoint pipe,
|
||||
uint32_t slot,
|
||||
const Rc<DxvkBufferView>& bufferView) {
|
||||
auto rc = this->getShaderResourceSlots(pipe);
|
||||
|
||||
m_flags.set(
|
||||
DxvkContextFlag::GpDirtyPipeline,
|
||||
DxvkContextFlag::GpDirtyResources,
|
||||
DxvkContextFlag::GpDirtyVertexBuffers,
|
||||
DxvkContextFlag::GpDirtyIndexBuffer);
|
||||
if (rc->getShaderResource(slot).bufferView != bufferView) {
|
||||
m_flags.set(this->getResourceDirtyFlag(pipe));
|
||||
|
||||
DxvkShaderResourceSlot resource;
|
||||
resource.bufferView = bufferView;
|
||||
|
||||
DxvkDescriptorInfo descriptor;
|
||||
|
||||
if (bufferView != nullptr)
|
||||
descriptor.texelBuffer = bufferView->handle();
|
||||
|
||||
rc->bindShaderResource(slot, resource, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindResourceImage(
|
||||
VkPipelineBindPoint pipe,
|
||||
uint32_t slot,
|
||||
const Rc<DxvkImageView>& image) {
|
||||
auto rc = this->getShaderResourceSlots(pipe);
|
||||
|
||||
if (rc->getShaderResource(slot).imageView != image) {
|
||||
m_flags.set(this->getResourceDirtyFlag(pipe));
|
||||
|
||||
DxvkShaderResourceSlot resource;
|
||||
resource.imageView = image;
|
||||
|
||||
DxvkDescriptorInfo descriptor;
|
||||
|
||||
if (image != nullptr) {
|
||||
descriptor.image.imageView = image->handle();
|
||||
descriptor.image.imageLayout = image->imageLayout();
|
||||
}
|
||||
|
||||
rc->bindShaderResource(slot, resource, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindResourceSampler(
|
||||
VkPipelineBindPoint pipe,
|
||||
uint32_t slot,
|
||||
const Rc<DxvkSampler>& sampler) {
|
||||
auto rc = this->getShaderResourceSlots(pipe);
|
||||
|
||||
if (rc->getShaderResource(slot).sampler != sampler) {
|
||||
m_flags.set(this->getResourceDirtyFlag(pipe));
|
||||
|
||||
DxvkShaderResourceSlot resource;
|
||||
resource.sampler = sampler;
|
||||
|
||||
DxvkDescriptorInfo descriptor;
|
||||
|
||||
if (sampler != nullptr)
|
||||
descriptor.image.sampler = sampler->handle();
|
||||
|
||||
rc->bindShaderResource(slot, resource, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -166,6 +260,8 @@ namespace dxvk {
|
||||
this->commitComputeState();
|
||||
|
||||
m_cmd->cmdDispatch(x, y, z);
|
||||
|
||||
this->commitComputeBarriers();
|
||||
}
|
||||
|
||||
|
||||
@ -335,12 +431,18 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindComputePipeline() {
|
||||
// TODO implement
|
||||
void DxvkContext::updateComputePipeline() {
|
||||
if (m_flags.test(DxvkContextFlag::CpDirtyPipeline)) {
|
||||
m_flags.clr(DxvkContextFlag::CpDirtyPipeline);
|
||||
|
||||
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
m_state.cPipe->getPipelineHandle());
|
||||
m_cmd->trackResource(m_state.cPipe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::bindGraphicsPipeline() {
|
||||
void DxvkContext::updateGraphicsPipeline() {
|
||||
if (m_flags.test(DxvkContextFlag::GpDirtyPipeline)) {
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyPipeline);
|
||||
|
||||
@ -355,8 +457,42 @@ namespace dxvk {
|
||||
gpState.viewportCount = m_state.vp.viewportCount;
|
||||
|
||||
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
m_state.gp->getPipelineHandle(gpState));
|
||||
m_cmd->trackResource(m_state.gp);
|
||||
m_state.gPipe->getPipelineHandle(gpState));
|
||||
m_cmd->trackResource(m_state.gPipe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::updateComputeShaderResources() {
|
||||
if (m_flags.test(DxvkContextFlag::CpDirtyResources)) {
|
||||
m_flags.clr(DxvkContextFlag::CpDirtyResources);
|
||||
|
||||
auto layout = m_state.cPipe->layout();
|
||||
|
||||
m_cmd->bindResourceDescriptors(
|
||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
layout->pipelineLayout(),
|
||||
layout->descriptorSetLayout(),
|
||||
layout->bindingCount(),
|
||||
layout->bindings(),
|
||||
m_cResources.descriptors());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::updateGraphicsShaderResources() {
|
||||
if (m_flags.test(DxvkContextFlag::GpDirtyResources)) {
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyResources);
|
||||
|
||||
auto layout = m_state.gPipe->layout();
|
||||
|
||||
m_cmd->bindResourceDescriptors(
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
layout->pipelineLayout(),
|
||||
layout->descriptorSetLayout(),
|
||||
layout->bindingCount(),
|
||||
layout->bindings(),
|
||||
m_gResources.descriptors());
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,16 +549,41 @@ namespace dxvk {
|
||||
|
||||
void DxvkContext::commitComputeState() {
|
||||
this->renderPassEnd();
|
||||
this->bindComputePipeline();
|
||||
this->updateComputePipeline();
|
||||
this->updateComputeShaderResources();
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::commitGraphicsState() {
|
||||
this->renderPassBegin();
|
||||
this->bindGraphicsPipeline();
|
||||
this->updateGraphicsPipeline();
|
||||
this->updateDynamicState();
|
||||
this->updateIndexBufferBinding();
|
||||
this->updateVertexBufferBindings();
|
||||
this->updateGraphicsShaderResources();
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::commitComputeBarriers() {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
|
||||
DxvkShaderResourceSlots* DxvkContext::getShaderResourceSlots(VkPipelineBindPoint pipe) {
|
||||
switch (pipe) {
|
||||
case VK_PIPELINE_BIND_POINT_GRAPHICS: return &m_gResources;
|
||||
case VK_PIPELINE_BIND_POINT_COMPUTE : return &m_cResources;
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxvkContextFlag DxvkContext::getResourceDirtyFlag(VkPipelineBindPoint pipe) const {
|
||||
switch (pipe) {
|
||||
default:
|
||||
case VK_PIPELINE_BIND_POINT_GRAPHICS: return DxvkContextFlag::GpDirtyResources;
|
||||
case VK_PIPELINE_BIND_POINT_COMPUTE : return DxvkContextFlag::CpDirtyResources;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_barrier.h"
|
||||
#include "dxvk_binding.h"
|
||||
#include "dxvk_cmdlist.h"
|
||||
#include "dxvk_context_state.h"
|
||||
#include "dxvk_data.h"
|
||||
@ -53,19 +54,8 @@ namespace dxvk {
|
||||
void bindFramebuffer(
|
||||
const Rc<DxvkFramebuffer>& fb);
|
||||
|
||||
/**
|
||||
* \brief Binds index buffer
|
||||
* \param [in] buffer New index buffer
|
||||
*/
|
||||
void bindIndexBuffer(
|
||||
const DxvkBufferBinding& buffer);
|
||||
|
||||
/**
|
||||
* \brief Binds compute pipeline
|
||||
*
|
||||
* Note that binding a new pipeline implicitly
|
||||
* invalidates all resource bindings that are
|
||||
* used by the pipeline.
|
||||
* \param [in] pipeline The pipeline to bind
|
||||
*/
|
||||
void bindComputePipeline(
|
||||
@ -73,15 +63,76 @@ namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Binds graphics pipeline
|
||||
*
|
||||
* Note that binding a new pipeline implicitly
|
||||
* invalidates all bindings that are used by
|
||||
* the pipeline.
|
||||
* \param [in] pipeline The pipeline to bind
|
||||
*/
|
||||
void bindGraphicsPipeline(
|
||||
const Rc<DxvkGraphicsPipeline>& pipeline);
|
||||
|
||||
/**
|
||||
* \brief Binds index buffer
|
||||
*
|
||||
* The index buffer will be used when
|
||||
* issuing \c drawIndexed commands.
|
||||
* \param [in] buffer New index buffer
|
||||
*/
|
||||
void bindIndexBuffer(
|
||||
const DxvkBufferBinding& buffer);
|
||||
|
||||
/**
|
||||
* \brief Binds buffer as a shader resource
|
||||
*
|
||||
* Can be used for uniform and storage buffers.
|
||||
* \param [in] pipe Target pipeline
|
||||
* \param [in] slot Resource binding slot
|
||||
* \param [in] buffer Buffer to bind
|
||||
*/
|
||||
void bindResourceBuffer(
|
||||
VkPipelineBindPoint pipe,
|
||||
uint32_t slot,
|
||||
const DxvkBufferBinding& buffer);
|
||||
|
||||
/**
|
||||
* \brief Binds texel buffer view
|
||||
*
|
||||
* Can be used for both uniform texel
|
||||
* buffers and storage texel buffers.
|
||||
* \param [in] pipe Target pipeline
|
||||
* \param [in] slot Resource binding slot
|
||||
* \param [in] bufferView Buffer view to bind
|
||||
*/
|
||||
void bindResourceTexelBuffer(
|
||||
VkPipelineBindPoint pipe,
|
||||
uint32_t slot,
|
||||
const Rc<DxvkBufferView>& bufferView);
|
||||
|
||||
/**
|
||||
* \brief Binds image view
|
||||
*
|
||||
* Can be used for sampled images with a
|
||||
* dedicated sampler and storage images.
|
||||
* \param [in] pipe Target pipeline
|
||||
* \param [in] slot Resource binding slot
|
||||
* \param [in] imageView Image view to bind
|
||||
*/
|
||||
void bindResourceImage(
|
||||
VkPipelineBindPoint pipe,
|
||||
uint32_t slot,
|
||||
const Rc<DxvkImageView>& image);
|
||||
|
||||
/**
|
||||
* \brief Binds image sampler
|
||||
*
|
||||
* Binds a sampler that can be used together with
|
||||
* an image in order to read from a texture.
|
||||
* \param [in] pipe Target pipeline
|
||||
* \param [in] slot Resource binding slot
|
||||
* \param [in] sampler Sampler view to bind
|
||||
*/
|
||||
void bindResourceSampler(
|
||||
VkPipelineBindPoint pipe,
|
||||
uint32_t slot,
|
||||
const Rc<DxvkSampler>& sampler);
|
||||
|
||||
/**
|
||||
* \brief Binds vertex buffer
|
||||
*
|
||||
@ -262,13 +313,17 @@ namespace dxvk {
|
||||
DxvkContextState m_state;
|
||||
DxvkBarrierSet m_barriers;
|
||||
|
||||
std::vector<VkWriteDescriptorSet> m_descriptorSetWrites;
|
||||
DxvkShaderResourceSlots m_cResources = { 1024 };
|
||||
DxvkShaderResourceSlots m_gResources = { 4096 };
|
||||
|
||||
void renderPassBegin();
|
||||
void renderPassEnd();
|
||||
|
||||
void bindComputePipeline();
|
||||
void bindGraphicsPipeline();
|
||||
void updateComputePipeline();
|
||||
void updateGraphicsPipeline();
|
||||
|
||||
void updateComputeShaderResources();
|
||||
void updateGraphicsShaderResources();
|
||||
|
||||
void updateDynamicState();
|
||||
void updateViewports();
|
||||
@ -278,6 +333,15 @@ namespace dxvk {
|
||||
|
||||
void commitComputeState();
|
||||
void commitGraphicsState();
|
||||
|
||||
void commitComputeBarriers();
|
||||
|
||||
DxvkShaderResourceSlots* getShaderResourceSlots(
|
||||
VkPipelineBindPoint pipe);
|
||||
|
||||
DxvkContextFlag getResourceDirtyFlag(
|
||||
VkPipelineBindPoint pipe) const;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -7,6 +7,8 @@
|
||||
#include "dxvk_graphics.h"
|
||||
#include "dxvk_image.h"
|
||||
#include "dxvk_limits.h"
|
||||
#include "dxvk_pipeline.h"
|
||||
#include "dxvk_sampler.h"
|
||||
#include "dxvk_shader.h"
|
||||
|
||||
namespace dxvk {
|
||||
@ -64,8 +66,8 @@ namespace dxvk {
|
||||
DxvkOutputMergerState om;
|
||||
DxvkConstantStateObjects co;
|
||||
|
||||
Rc<DxvkGraphicsPipeline> gp;
|
||||
Rc<DxvkComputePipeline> cp;
|
||||
Rc<DxvkGraphicsPipeline> gPipe;
|
||||
Rc<DxvkComputePipeline> cPipe;
|
||||
};
|
||||
|
||||
}
|
@ -4,6 +4,19 @@
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Descriptor info
|
||||
*
|
||||
* Stores information that is required to
|
||||
* update a single resource descriptor.
|
||||
*/
|
||||
struct DxvkDescriptorInfo {
|
||||
VkDescriptorImageInfo image = { VK_NULL_HANDLE, VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED };
|
||||
VkDescriptorBufferInfo buffer = { VK_NULL_HANDLE, 0, 0 };
|
||||
VkBufferView texelBuffer = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Descriptor set allocator
|
||||
*
|
||||
|
@ -79,6 +79,12 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkSampler> DxvkDevice::createSampler(
|
||||
const DxvkSamplerCreateInfo& createInfo) {
|
||||
return new DxvkSampler(m_vkd, createInfo);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkSemaphore> DxvkDevice::createSemaphore() {
|
||||
return new DxvkSemaphore(m_vkd);
|
||||
}
|
||||
@ -92,8 +98,8 @@ namespace dxvk {
|
||||
|
||||
|
||||
Rc<DxvkBindingLayout> DxvkDevice::createBindingLayout(
|
||||
uint32_t bindingCount,
|
||||
const DxvkBindingInfo* bindingInfos) {
|
||||
uint32_t bindingCount,
|
||||
const DxvkDescriptorSlot* bindingInfos) {
|
||||
return new DxvkBindingLayout(m_vkd, bindingCount, bindingInfos);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "dxvk_image.h"
|
||||
#include "dxvk_memory.h"
|
||||
#include "dxvk_renderpass.h"
|
||||
#include "dxvk_sampler.h"
|
||||
#include "dxvk_shader.h"
|
||||
#include "dxvk_swapchain.h"
|
||||
#include "dxvk_sync.h"
|
||||
@ -141,6 +142,15 @@ namespace dxvk {
|
||||
const Rc<DxvkImage>& image,
|
||||
const DxvkImageViewCreateInfo& createInfo);
|
||||
|
||||
/**
|
||||
* \brief Creates a sampler object
|
||||
*
|
||||
* \param [in] createInfo Sampler parameters
|
||||
* \returns Newly created sampler object
|
||||
*/
|
||||
Rc<DxvkSampler> createSampler(
|
||||
const DxvkSamplerCreateInfo& createInfo);
|
||||
|
||||
/**
|
||||
* \brief Creates a semaphore object
|
||||
* \returns Newly created semaphore
|
||||
@ -166,8 +176,8 @@ namespace dxvk {
|
||||
* \returns New binding layout
|
||||
*/
|
||||
Rc<DxvkBindingLayout> createBindingLayout(
|
||||
uint32_t bindingCount,
|
||||
const DxvkBindingInfo* bindingInfos);
|
||||
uint32_t bindingCount,
|
||||
const DxvkDescriptorSlot* bindingInfos);
|
||||
|
||||
/**
|
||||
* \brief Creates a compute pipeline
|
||||
|
@ -119,7 +119,7 @@ namespace dxvk {
|
||||
info.pDepthStencilState = &state.depthStencilState->info();
|
||||
info.pColorBlendState = &state.blendState->info();
|
||||
info.pDynamicState = &dsInfo;
|
||||
info.layout = this->pipelineLayout();
|
||||
info.layout = m_layout->pipelineLayout();
|
||||
info.renderPass = state.renderPass;
|
||||
info.subpass = 0;
|
||||
info.basePipelineHandle = VK_NULL_HANDLE;
|
||||
|
@ -58,26 +58,16 @@ namespace dxvk {
|
||||
const Rc<DxvkShader>& fs);
|
||||
~DxvkGraphicsPipeline();
|
||||
|
||||
/**
|
||||
* \brief Descriptor set layout
|
||||
*
|
||||
* The descriptor set layout for this pipeline.
|
||||
* Use this to allocate new descriptor sets.
|
||||
* \returns The descriptor set layout
|
||||
*/
|
||||
VkDescriptorSetLayout descriptorSetLayout() const {
|
||||
return m_layout->descriptorSetLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Pipeline layout
|
||||
*
|
||||
* The pipeline layout for this pipeline.
|
||||
* Use this to bind descriptor sets.
|
||||
* \returns The descriptor set layout
|
||||
* Stores the pipeline layout and the descriptor set
|
||||
* layout, as well as information on the resource
|
||||
* slots used by the pipeline.
|
||||
* \returns Pipeline layout
|
||||
*/
|
||||
VkPipelineLayout pipelineLayout() const {
|
||||
return m_layout->pipelineLayout();
|
||||
Rc<DxvkBindingLayout> layout() const {
|
||||
return m_layout;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -178,6 +178,14 @@ namespace dxvk {
|
||||
return m_image;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Image layout
|
||||
* \returns Image layout
|
||||
*/
|
||||
VkImageLayout imageLayout() const {
|
||||
return m_image->info().layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Subresource range
|
||||
* \returns Subresource range
|
||||
|
@ -5,11 +5,12 @@
|
||||
namespace dxvk {
|
||||
|
||||
enum DxvkLimits : size_t {
|
||||
MaxNumRenderTargets = 8,
|
||||
MaxNumVertexAttributes = 32,
|
||||
MaxNumVertexBindings = 32,
|
||||
MaxNumOutputStreams = 4,
|
||||
MaxNumViewports = 16,
|
||||
MaxNumRenderTargets = 8,
|
||||
MaxNumVertexAttributes = 32,
|
||||
MaxNumVertexBindings = 32,
|
||||
MaxNumOutputStreams = 4,
|
||||
MaxNumViewports = 16,
|
||||
MaxNumResourceSlots = 4096,
|
||||
};
|
||||
|
||||
}
|
@ -1,29 +1,37 @@
|
||||
#include <cstring>
|
||||
|
||||
#include "dxvk_pipeline.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkBindingLayout::DxvkBindingLayout(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
uint32_t bindingCount,
|
||||
const DxvkBindingInfo* bindingInfos)
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
uint32_t bindingCount,
|
||||
const DxvkDescriptorSlot* bindingInfos)
|
||||
: m_vkd(vkd) {
|
||||
|
||||
m_bindingSlots.resize(bindingCount);
|
||||
std::memcpy(m_bindingSlots.data(), bindingInfos,
|
||||
bindingCount * sizeof(DxvkDescriptorSlot));
|
||||
|
||||
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
||||
|
||||
for (uint32_t i = 0; i < bindingCount; i++) {
|
||||
VkDescriptorSetLayoutBinding binding;
|
||||
binding.binding = i;
|
||||
binding.descriptorType = bindingInfos[i].type;
|
||||
binding.descriptorCount = bindingInfos[i].stages == 0 ? 0 : 1;
|
||||
binding.descriptorCount = 1;
|
||||
binding.stageFlags = bindingInfos[i].stages;
|
||||
binding.pImmutableSamplers = nullptr;
|
||||
m_bindings.push_back(binding);
|
||||
bindings.push_back(binding);
|
||||
}
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo dsetInfo;
|
||||
dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
dsetInfo.pNext = nullptr;
|
||||
dsetInfo.flags = 0;
|
||||
dsetInfo.bindingCount = m_bindings.size();
|
||||
dsetInfo.pBindings = m_bindings.data();
|
||||
dsetInfo.bindingCount = bindings.size();
|
||||
dsetInfo.pBindings = bindings.data();
|
||||
|
||||
if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(),
|
||||
&dsetInfo, nullptr, &m_descriptorSetLayout) != VK_SUCCESS)
|
||||
@ -59,14 +67,4 @@ namespace dxvk {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DxvkBindingInfo DxvkBindingLayout::binding(uint32_t id) const {
|
||||
const VkDescriptorSetLayoutBinding& bindingInfo = m_bindings.at(id);
|
||||
|
||||
DxvkBindingInfo result;
|
||||
result.type = bindingInfo.descriptorType;
|
||||
result.stages = bindingInfo.stageFlags;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -11,9 +11,10 @@ namespace dxvk {
|
||||
* Vulkan. DXVK does not use descriptor arrays.
|
||||
* Instead, each binding stores one descriptor.
|
||||
*/
|
||||
struct DxvkBindingInfo {
|
||||
VkDescriptorType type;
|
||||
VkShaderStageFlags stages;
|
||||
struct DxvkDescriptorSlot {
|
||||
uint32_t slot; ///< Resource slot index for the context
|
||||
VkDescriptorType type; ///< Descriptor type (aka resource type)
|
||||
VkShaderStageFlags stages; ///< Stages that can use the resource
|
||||
};
|
||||
|
||||
|
||||
@ -28,9 +29,9 @@ namespace dxvk {
|
||||
public:
|
||||
|
||||
DxvkBindingLayout(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
uint32_t bindingCount,
|
||||
const DxvkBindingInfo* bindingInfos);
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
uint32_t bindingCount,
|
||||
const DxvkDescriptorSlot* bindingInfos);
|
||||
|
||||
~DxvkBindingLayout();
|
||||
|
||||
@ -38,17 +39,17 @@ namespace dxvk {
|
||||
* \brief Number of resource bindings
|
||||
* \returns Resource binding count
|
||||
*/
|
||||
uint32_t numBindings() const {
|
||||
return m_bindings.size();
|
||||
uint32_t bindingCount() const {
|
||||
return m_bindingSlots.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves binding info
|
||||
*
|
||||
* \param [in] binding ID
|
||||
* \returns Binding info
|
||||
* \brief Resource binding info
|
||||
* \returns Resource binding info
|
||||
*/
|
||||
DxvkBindingInfo binding(uint32_t id) const;
|
||||
const DxvkDescriptorSlot* bindings() const {
|
||||
return m_bindingSlots.data();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Descriptor set layout handle
|
||||
@ -73,7 +74,7 @@ namespace dxvk {
|
||||
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
|
||||
|
||||
std::vector<VkDescriptorSetLayoutBinding> m_bindings;
|
||||
std::vector<DxvkDescriptorSlot> m_bindingSlots;
|
||||
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
#include "dxvk_sampler.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
DxvkSampler::DxvkSampler(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkSamplerCreateInfo& info)
|
||||
: m_vkd(vkd), m_info(info) {
|
||||
VkSamplerCreateInfo samplerInfo;
|
||||
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
samplerInfo.pNext = nullptr;
|
||||
samplerInfo.flags = 0;
|
||||
samplerInfo.magFilter = info.magFilter;
|
||||
samplerInfo.minFilter = info.minFilter;
|
||||
samplerInfo.mipmapMode = info.mipmapMode;
|
||||
samplerInfo.addressModeU = info.addressModeU;
|
||||
samplerInfo.addressModeV = info.addressModeV;
|
||||
samplerInfo.addressModeW = info.addressModeW;
|
||||
samplerInfo.mipLodBias = info.mipmapLodBias;
|
||||
samplerInfo.anisotropyEnable = info.useAnisotropy;
|
||||
samplerInfo.maxAnisotropy = info.maxAnisotropy;
|
||||
samplerInfo.compareEnable = info.compareToDepth;
|
||||
samplerInfo.compareOp = info.compareOp;
|
||||
samplerInfo.minLod = info.mipmapLodMin;
|
||||
samplerInfo.maxLod = info.mipmapLodMax;
|
||||
samplerInfo.borderColor = info.borderColor;
|
||||
samplerInfo.unnormalizedCoordinates = info.usePixelCoord;
|
||||
|
||||
if (m_vkd->vkCreateSampler(m_vkd->device(),
|
||||
&samplerInfo, nullptr, &m_sampler) != VK_SUCCESS)
|
||||
throw DxvkError("DxvkSampler::DxvkSampler: Failed to create sampler");
|
||||
}
|
||||
|
||||
|
||||
DxvkSampler::~DxvkSampler() {
|
||||
m_vkd->vkDestroySampler(
|
||||
m_vkd->device(), m_sampler, nullptr);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include "dxvk_resource.h"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
/**
|
||||
* \brief Sampler properties
|
||||
*/
|
||||
struct DxvkSamplerCreateInfo {
|
||||
/// Texture filter propertoes
|
||||
VkFilter magFilter;
|
||||
VkFilter minFilter;
|
||||
|
||||
/// Mipmapping properties
|
||||
VkSamplerMipmapMode mipmapMode;
|
||||
float mipmapLodBias;
|
||||
float mipmapLodMin;
|
||||
float mipmapLodMax;
|
||||
|
||||
/// Anisotropic filtering
|
||||
VkBool32 useAnisotropy;
|
||||
float maxAnisotropy;
|
||||
|
||||
/// Address modes
|
||||
VkSamplerAddressMode addressModeU;
|
||||
VkSamplerAddressMode addressModeV;
|
||||
VkSamplerAddressMode addressModeW;
|
||||
|
||||
/// Compare op for shadow textures
|
||||
VkBool32 compareToDepth;
|
||||
VkCompareOp compareOp;
|
||||
|
||||
/// Texture border color
|
||||
VkBorderColor borderColor;
|
||||
|
||||
/// Enables unnormalized coordinates
|
||||
VkBool32 usePixelCoord;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Sampler
|
||||
*
|
||||
* Manages a sampler object that can be bound to
|
||||
* a pipeline. Sampler objects provide parameters
|
||||
* for texture lookups within a shader.
|
||||
*/
|
||||
class DxvkSampler : public DxvkResource {
|
||||
|
||||
public:
|
||||
|
||||
DxvkSampler(
|
||||
const Rc<vk::DeviceFn>& vkd,
|
||||
const DxvkSamplerCreateInfo& info);
|
||||
~DxvkSampler();
|
||||
|
||||
/**
|
||||
* \brief Sampler handle
|
||||
* \returns Sampler handle
|
||||
*/
|
||||
VkSampler handle() const {
|
||||
return m_sampler;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sampler parameters
|
||||
* \returns Sampler parameters
|
||||
*/
|
||||
const DxvkSamplerCreateInfo& info() const {
|
||||
return m_info;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Rc<vk::DeviceFn> m_vkd;
|
||||
DxvkSamplerCreateInfo m_info;
|
||||
VkSampler m_sampler = VK_NULL_HANDLE;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -19,6 +19,7 @@ dxvk_src = files([
|
||||
'dxvk_pipeline.cpp',
|
||||
'dxvk_renderpass.cpp',
|
||||
'dxvk_resource.cpp',
|
||||
'dxvk_sampler.cpp',
|
||||
'dxvk_shader.cpp',
|
||||
'dxvk_surface.cpp',
|
||||
'dxvk_swapchain.cpp',
|
||||
|
@ -221,6 +221,16 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void SpirvModule::decorateBinding(
|
||||
uint32_t object,
|
||||
uint32_t binding) {
|
||||
m_annotations.putIns (spv::OpDecorate, 4);
|
||||
m_annotations.putWord (object);
|
||||
m_annotations.putWord (spv::DecorationBinding);
|
||||
m_annotations.putInt32(binding);
|
||||
}
|
||||
|
||||
|
||||
void SpirvModule::decorateBlock(uint32_t object) {
|
||||
m_annotations.putIns (spv::OpDecorate, 3);
|
||||
m_annotations.putWord (object);
|
||||
@ -248,6 +258,16 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void SpirvModule::decorateDescriptorSet(
|
||||
uint32_t object,
|
||||
uint32_t set) {
|
||||
m_annotations.putIns (spv::OpDecorate, 4);
|
||||
m_annotations.putWord (object);
|
||||
m_annotations.putWord (spv::DecorationDescriptorSet);
|
||||
m_annotations.putInt32(set);
|
||||
}
|
||||
|
||||
|
||||
void SpirvModule::decorateLocation(
|
||||
uint32_t object,
|
||||
uint32_t location) {
|
||||
@ -378,6 +398,36 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::defSamplerType() {
|
||||
return this->defType(spv::OpTypeSampler, 0, nullptr);
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::defImageType(
|
||||
uint32_t sampledType,
|
||||
spv::Dim dimensionality,
|
||||
uint32_t depth,
|
||||
uint32_t arrayed,
|
||||
uint32_t multisample,
|
||||
uint32_t sampled,
|
||||
spv::ImageFormat format) {
|
||||
std::array<uint32_t, 7> args = {
|
||||
sampledType, dimensionality,
|
||||
depth, arrayed, multisample,
|
||||
sampled, format
|
||||
};
|
||||
|
||||
return this->defType(spv::OpTypeImage,
|
||||
args.size(), args.data());
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::defSampledImageType(
|
||||
uint32_t imageType) {
|
||||
return this->defType(spv::OpTypeSampledImage, 1, &imageType);
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::newVar(
|
||||
uint32_t pointerType,
|
||||
spv::StorageClass storageClass) {
|
||||
@ -675,6 +725,36 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opSampledImage(
|
||||
uint32_t resultType,
|
||||
uint32_t image,
|
||||
uint32_t sampler) {
|
||||
uint32_t resultId = this->allocateId();
|
||||
|
||||
m_code.putIns (spv::OpSampledImage, 5);
|
||||
m_code.putWord(resultType);
|
||||
m_code.putWord(resultId);
|
||||
m_code.putWord(image);
|
||||
m_code.putWord(sampler);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opImageSampleImplicitLod(
|
||||
uint32_t resultType,
|
||||
uint32_t sampledImage,
|
||||
uint32_t coordinates) {
|
||||
uint32_t resultId = this->allocateId();
|
||||
|
||||
m_code.putIns (spv::OpImageSampleImplicitLod, 5);
|
||||
m_code.putWord(resultType);
|
||||
m_code.putWord(resultId);
|
||||
m_code.putWord(sampledImage);
|
||||
m_code.putWord(coordinates);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
void SpirvModule::opReturn() {
|
||||
m_code.putIns (spv::OpReturn, 1);
|
||||
}
|
||||
|
@ -81,6 +81,10 @@ namespace dxvk {
|
||||
uint32_t constCount,
|
||||
const uint32_t* constIds);
|
||||
|
||||
void decorateBinding(
|
||||
uint32_t object,
|
||||
uint32_t binding);
|
||||
|
||||
void decorateBlock(
|
||||
uint32_t object);
|
||||
|
||||
@ -92,6 +96,10 @@ namespace dxvk {
|
||||
uint32_t object,
|
||||
uint32_t location);
|
||||
|
||||
void decorateDescriptorSet(
|
||||
uint32_t object,
|
||||
uint32_t set);
|
||||
|
||||
void decorateLocation(
|
||||
uint32_t object,
|
||||
uint32_t location);
|
||||
@ -140,6 +148,20 @@ namespace dxvk {
|
||||
uint32_t variableType,
|
||||
spv::StorageClass storageClass);
|
||||
|
||||
uint32_t defSamplerType();
|
||||
|
||||
uint32_t defImageType(
|
||||
uint32_t sampledType,
|
||||
spv::Dim dimensionality,
|
||||
uint32_t depth,
|
||||
uint32_t arrayed,
|
||||
uint32_t multisample,
|
||||
uint32_t sampled,
|
||||
spv::ImageFormat format);
|
||||
|
||||
uint32_t defSampledImageType(
|
||||
uint32_t imageType);
|
||||
|
||||
uint32_t newVar(
|
||||
uint32_t pointerType,
|
||||
spv::StorageClass storageClass);
|
||||
@ -239,6 +261,16 @@ namespace dxvk {
|
||||
uint32_t pointerId,
|
||||
uint32_t valueId);
|
||||
|
||||
uint32_t opSampledImage(
|
||||
uint32_t resultType,
|
||||
uint32_t image,
|
||||
uint32_t sampler);
|
||||
|
||||
uint32_t opImageSampleImplicitLod(
|
||||
uint32_t resultType,
|
||||
uint32_t sampledImage,
|
||||
uint32_t coordinates);
|
||||
|
||||
void opReturn();
|
||||
|
||||
private:
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
|
||||
|
||||
void run() {
|
||||
FLOAT color[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
FLOAT color[4] = { 0.8f, 0.2f, 0.2f, 1.0f };
|
||||
|
||||
m_context->OMSetRenderTargets(1, &m_bufferView, nullptr);
|
||||
m_context->ClearRenderTargetView(m_bufferView.ptr(), color);
|
||||
|
Loading…
x
Reference in New Issue
Block a user