[D3D12] Constant buffer binding

This commit is contained in:
Triang3l
2018-07-30 15:59:43 +03:00
parent 84e7ae16e7
commit e0eede73b9
9 changed files with 857 additions and 350 deletions

View File

@@ -68,8 +68,8 @@ void UploadBufferPool::ClearCache() {
uint8_t* UploadBufferPool::RequestFull(uint32_t size,
ID3D12Resource*& buffer_out,
uint32_t& offset_out) {
assert_true(size != 0 && size <= page_size_);
if (size == 0 || size > page_size_) {
assert_true(size <= page_size_);
if (size > page_size_) {
return nullptr;
}
if (page_size_ - current_size_ < size || current_mapping_ == nullptr) {
@@ -89,10 +89,6 @@ uint8_t* UploadBufferPool::RequestPartial(uint32_t size,
ID3D12Resource*& buffer_out,
uint32_t& offset_out,
uint32_t& size_out) {
assert_true(size != 0);
if (size == 0) {
return nullptr;
}
if (current_size_ == page_size_ || current_mapping_ == nullptr) {
// Start a new page if can't fit any bytes or don't have an open page.
if (!BeginNextPage()) {
@@ -216,7 +212,7 @@ void DescriptorHeapPool::BeginFrame() {
void DescriptorHeapPool::EndFrame() { EndPage(); }
void DescriptorHeapPool::ClearCache() {
assert(current_size_ == 0);
assert_true(current_size_ == 0);
while (unsent_ != nullptr) {
auto next = unsent_->next;
unsent_->heap->Release();
@@ -232,36 +228,39 @@ void DescriptorHeapPool::ClearCache() {
sent_last_ = nullptr;
}
uint64_t DescriptorHeapPool::GetPageForRequest(uint32_t count) const {
uint64_t page = current_page_;
if (page_size_ - current_size_ < count) {
++page;
}
return page;
}
bool DescriptorHeapPool::Request(uint32_t count, uint32_t& index_out) {
assert_true(count != 0 && count <= page_size_);
if (count == 0 || count > page_size_) {
return false;
uint64_t DescriptorHeapPool::Request(uint64_t previous_full_update,
uint32_t count_for_partial_update,
uint32_t count_for_full_update,
uint32_t& index_out) {
assert_true(count_for_partial_update <= count_for_full_update);
assert_true(count_for_full_update <= page_size_);
if (count_for_partial_update > count_for_full_update ||
count_for_full_update > page_size_) {
return 0;
}
if (page_creation_failed_) {
// Don't increment the page index every call if there was a failure as well.
return false;
// Don't touch the page index every call if there was a failure as well.
return 0;
}
// Go to the next page if there's not enough free space on the current one.
// If the last full update happened on the current page, a partial update is
// possible.
uint32_t count = previous_full_update == current_page_
? count_for_partial_update
: count_for_full_update;
// Go to the next page if there's not enough free space on the current one,
// or because the previous page may be outdated. In this case, a full update
// is necessary.
if (page_size_ - current_size_ < count) {
EndPage();
++current_page_;
count = count_for_full_update;
}
// Create the page if needed (may be the first call for the page).
if (unsent_ == nullptr) {
if (page_creation_failed_) {
return false;
}
auto device = context_->GetD3D12Provider()->GetDevice();
D3D12_DESCRIPTOR_HEAP_DESC heap_desc;
heap_desc.Type = type_;
@@ -273,7 +272,7 @@ bool DescriptorHeapPool::Request(uint32_t count, uint32_t& index_out) {
XELOGE("Failed to create a heap for %u shader-visible descriptors",
page_size_);
page_creation_failed_ = true;
return false;
return 0;
}
unsent_ = new DescriptorHeap;
unsent_->heap = heap;
@@ -289,7 +288,7 @@ bool DescriptorHeapPool::Request(uint32_t count, uint32_t& index_out) {
}
index_out = current_size_;
current_size_ += count;
return true;
return current_page_;
}
void DescriptorHeapPool::EndPage() {

View File

@@ -71,13 +71,34 @@ class DescriptorHeapPool {
void EndFrame();
void ClearCache();
// To check if a rebind will be required, and thus may possibly need to write
// all the descriptors needed for a draw call rather than only the modified
// ones. The page number can never be 0 if a frame has started, and it's
// changed every frame, so it's safe to use 0 to indicate that the descriptors
// for some data have never been written.
uint64_t GetPageForRequest(uint32_t count) const;
bool Request(uint32_t count, uint32_t& index_out);
// Because all descriptors for a single draw call must be in the same heap,
// sometimes all descriptors, rather than only the modified portion of it,
// needs to be written.
//
// This may happen if there's not enough free space even for a partial update
// in the current heap, or if the heap which contains the unchanged part of
// the descriptors is outdated.
//
// If something uses this pool to do partial updates, it must let this
// function determine whether a partial update is possible. For this purpose,
// this function returns a full update number - and it must be called with its
// previous return value for the set of descriptors it's updating.
//
// If this function returns a value that is the same as previous_full_update,
// a partial update needs to be done - and space for count_for_partial_update
// is allocated.
//
// If it's different, all descriptors must be written again - and space for
// count_for_full_update is allocated.
//
// If 0 is returned, there was an error.
//
// This MUST be called even if there's nothing to write in a partial update
// (with count_for_partial_update being 0), because a full update may still be
// required.
uint64_t Request(uint64_t previous_full_update,
uint32_t count_for_partial_update,
uint32_t count_for_full_update, uint32_t& index_out);
// The current heap, for binding and actually writing - may be called only
// after a successful request because before a request, the heap may not exist
@@ -89,7 +110,6 @@ class DescriptorHeapPool {
D3D12_GPU_DESCRIPTOR_HANDLE GetLastRequestHeapGPUStart() const {
return current_heap_gpu_start_;
}
uint64_t GetLastRequestPageNumber() const { return current_page_; }
private:
D3D12Context* context_;